ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링 부트에서 JPA 데이터베이스 사용하기
    Spring_FrameWork 2020. 6. 6. 18:09
    • 스프링에서는 대부분 MyBatis(SQL매퍼)를 이용해서 데이터베이스 쿼리를 작성한다. 
    1. 그러다 보니 실제 개발하는 시간보다 SQL을 다루는 시간이 많고 
    2. 객체 모델링보다 테이블 모델링에 집중하게 되며 객체를 단순히 테이블에 맞추어 데이터를 전달하는 
    3. 기형적인 형태가 된다.
    4. 이 문제의 해결책으로 JPA라는 자바 표준 ORM 기술이 있다. 

    JPA 소개 

    애플리케이션에서 DB를 쓰지 않는 경우는 거의 없다. 

    객체를 데이터 베이스에서 관리하는 것이 굉장히 중요하다.

    현업 프로젝트 대부분이 애플리케이션 코드보다. SQL로 가득하게 된다. 

    굉장히 데이터베이스 규모가 커질수록 SQL에 대한 반복 작업은 심해진다. 

    이런 반복작업 문제 외에도 한 가지 문제가 더 있다. 

    패러다임의 불일치 문제 관계형 데이터베이스는 어떻게 데이터를 저장할지 초점이 맞혀진 기술

    반대로 객체지향 프로그래밍 언어는 메시지를 기반으로 기능과 속성을 한 곳에 관리하는 기술

    두개의 패러다임을 일치시켜주기 위한 기술이다. 

     

    개발자는 객체지향적으로 프로그래밍을 하고 JPA가 이를 관계형 데이터 베이스에 맞게 SQL을 대신 생성해서 실행한다. 

    장점 유지보수가 쉬워짐 

    Spring Data JPA 

    JPA는 인터페이스로서 자바 표준 명세서이다. 

    인터페이스인 JPA를 사용하기위해서는 구현체가 필요하다. 

    Hibernate, EclipseLink 등이 있다. 

    이 구현체들을 추상화 시킨 Spring Data JPA라는 모듈을 이용해서 JPA 기술을 다룬다. 

    Spring Data JPA 가 등장한 이유 

    • 구현체 교체의 용이성
    • 저장소 교체의 용이성

    실무에서 JPA 

    실무에서 JPA를 사용하지 못하는 가장 큰 이유 높은 이유는 큰 러닝 커브 

    객체지향 프로그래밍, 관계형 데이터 베이스 둘 다 이해를 해야 함 

    요구사항 분석

    게시판 요구사항

    게시판 기능 회원기능
    게시글 조회
    게시글 등록
    게시글 수정
    게시글 삭제
    구글/네이버 로그인
    로그인한 사용자 글 작성권한
    본인 작성 글에 대한 권한 권리 

     

    프로젝트에 Spring Data Jpa 적용하기 

    build.gradle 에 의존성 추가 

    1. spring-boot-starter-data-jpa

    2. h2 데이터 베이스 - 메모리에서 실행되므로 애플리케이션이 재시작할 때마다 초기화 테스트에 많이 사용됨

    다음과 같은 패키지를 만든다. 

    도메인을 담을 패키지

    도메인이란? - 게시글, 댓글, 회원, 정산, 결제 등 소프트웨어에 대한 요구사항 혹은 문제 영역.

    DAO와는 다르다 , 기존에는 xml에 쿼리를 담고 클래스는 오로지 쿼리에 결과를 담음 

    하지만 JPA 도메인 클래스라고 불리는 곳에서 해결된다. 

    Post 패키지와 post 클래스 만듬 

    주요 어노테이션을 클래스에 가깝게 둔다. 

    getter(게터)와 NoargsConstructor(기본생성자가 매개변수가없음)는 롬복의 어노테이션 

    롬복은 코드를 단순화 시켜주지만 필수 어노테이션을 아니다. 

    여기서 Post 클래스는 실제 DB와 매칭이 될 클래스이며 보통 Entity 클래스라고함 

    JPA를 사용하면 DB 작업을 할 경우 쿼리를 날리기보다 해당 Entity 클래스의 수정을 통해 작업을 한다. 

    Post 클래스에는 JPA에서 제공하는 어노테이션이 몇개 존재한다. 

    어노테이션 설명 

    @Entity 

    • 테이블과 링크될 클래스임을 나타낸다. 
    • 기본값으로 클래스를 카멜케이스 이름을 언더스코어 네이밍으로 테이블이름을 매칭한다. 
    • 예)SalesManager.java -> sales_manager table

    @Id

    • PK의 생성 규칙을 나타낸다. 
    • 스프링 부트 2.0에서 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment가 된다. 
    • 스프링 부트 2.0과 1.5 차이는 https://jojoldu.tistory.com/295
     

    Spring Boot Data JPA 2.0 에서 id Auto_increment 문제 해결

    안녕하세요? 이번 시간엔 Spring Boot JPA 2.0 에서 PK의 Auto_increment 문제를 알아보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하�

    jojoldu.tistory.com

    @Column

    • 테이블의 컬럼을 나타내며 굳이 선언하지 않더라도 해당 클래스는 모두 칼럼이 됨 
    • 사용하는 이유는, 기본값 외 추가로 변경옵션이 있으면 사용한다.
    • 문자열의 경우 VARCHA(255)가 기본값인데 사이즈를 500으로 늘리고 싶거나(ex: title), 타입을 TEXT로 변경하고 싶거나(ex: content)등의 경우에만 사용된다. 
    웬만하면 Entity의 PK는  Long타입의 Auto_increment를 추천한다. (Mysql 기준은 Bigint가 됨)
    주민번호와 가팅 비즈니스상 유니크 키나, 여러키를 조합한 복합기로 PK로 잡을 경우 난감한 상황이 발생한다. 

    1. FK 를 맺을 때 다른테이블에서 복합기를 전부 갖고 있거나 , 중간 테이블을 하나둬야한느 상황이 생김
    2. 인덱스에 좋은 영향이 없음
    3. 유니크한 조건이 변경될경우 PK 전체를 수정해야하는 일이 생김 
    주민번호나 복합키등 유니크 키로 별도로 추가하는것을 추천 

     

    @NoArgsContructor

    • 기본생성자 

    @Getter 

    • Getter 메소드 자동생성
    • @Builder
    • 해당 클래스의 빌더 패턴 클래스 생성 
    • 생성자 상단에 선언시 생성자에 포함된 필드만 빌더에 포함 

    무턱대고 Setter를 만들 필요는 없다 . 

    Entity에서는 기본적으로 생성자로 최종값을 채운뒤 DB에 삽입하고 값 변경이 필요할시 

    해당 이벤트에 맞는 public 메소드를 호출하여 변경하는것을 전제로 한다. 

    Posts 클래스로 Database를 접근하게 해줄 JpaRepository를 생성한다. 

     

    보통 마이바티스에서 Dao 데이터 엑세스 오브젝트는 DB layer 접근자이다.

    JPA 에서 Repository라고 부르며 인터페이스로 생성한다. 

    단순히 인터 페이스를 생성한후 , JpaRepository<Entity 클래스, PK 타입>을 상속하면 기본적이 CRUD 메소드가 자동으로 생성 된다. 

    @Repository를 추가할 필요도 없다.

    주의점 : Entity 클래스와 기본 Entity Repository는 함께 위치 해야하는 점이다. 

    둘은 밀접한 관계이고 Entity 클래스는 기본 Repository 없이는 제대로 역할을 할 수가 없다.

    프로젝트가 커져서 도메인별로 프로젝트를 분리하게 된다면 Entity 클래스와 기본 Repository는 함께 움직여야하므로 도메인 패키지에서 관리한다. 

    3.3 Spring Data 테스트 코드 작성하기 

    test 디렉터리에 domain.posts 패키지를 생성하고 테스트 클래스는 PostsRepositoryTest 이름으로 생성한다.

    package com.kjh.book.springboot.web.domain.posts;
    
    import com.kjh.book.springboot.domain.posts.Posts;
    import com.kjh.book.springboot.domain.posts.PostsRepository;
    import org.junit.After;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class PostsRepositoryTest {
    
        @Autowired
        PostsRepository postsRepository;
    
        @After //1
        public void cleanup(){
            postsRepository.deleteAll();
        }
    
        @Test
        public void 게시글저장_불러오기(){
            //given
            String title = "테스트 게시글";
            String content = "테스트 본문";
    
            postsRepository.save(Posts.builder()//2
                            .title(title)
                            .content(content)
                            .author("example@gmail.com")
                            .build());
    
            //when
            List<Posts> postsList = postsRepository.findAll(); //3
    
            //then
            Posts posts = postsList.get(0);
            assertThat(posts.getTitle()).isEqualTo(title);
            assertThat(posts.getContent()).isEqualTo(content);
    
        }
    }
    

     

    코드설명

    1. @After

    • Junit에서 단위테스트가 끝날때 수행되는 메소드를 지정 
    • 보통은 배포전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용한다. 
    • 여러테스트가 통시에 수행되면서 테스트용 데이터 베이스인 H2에 데이터가 그대로 남아있어 다음 테스트가 실패할 수 있기 때문에 

    2. postsRepository.save

    • 테이블 posts에 insert/update 쿼리를 실행한다. 
    • id 값이 있다면 update가 없다면 , insert 쿼리가 실행된다.

    3. postsRepository.findAll

    • 테이블 posts에 있는 모든 데이터를 조사해오는 메소드 

     

    실제 실행된 쿼리 로그 보기 

    src/main/resource 디렉터리에 application.properties 파일을 생성한다. 

    spring.jpa.show_sql=true 

    설정을 추가 

    다음과 같이 쿼리가 표현된다.

    현재 테이블 생성쿼리를 보면

    h2 쿼리 설정이므로 다음과 같이 나타난다. 

    출력쿼리를 Mysql 버전으로 변경하려면 application.properties 에서 설정가능하다. 

    설정 추가 

    옵션이 잘 적용되었음이 확인 가능하다. 

    'Spring_FrameWork' 카테고리의 다른 글

    DB연동  (0) 2019.03.22
    AOP소개  (0) 2019.03.19
    빈 라이프사이클과 범위  (0) 2019.03.19
    DI정리  (0) 2019.03.18
    의존 자동 주입  (0) 2019.03.15
Designed by Tistory.