FrameWork/Spring

Spring Data JPA

태윤2 2021. 8. 18. 16:27

JPA는 인터페이스로서 자바 표준 명세서이다. 인터페이스인 JPA를 사용하기 위해서는 구현체가 필요한데 대표적으로는 Hibernate, EclipseLink 등 이 있습니다. 하지만 Spring에서 JPA를 사용할 때는 이 구현체들을 직접 다루진 않습니다..

구현체들을 좀더 쉽게 사용하고자 추상화시킨 Spring Data JPA라는 모듈을 이용해 JPA 기술을 다룹니다. 

  • JPA <- Hibernate <- Spring Data JPA

Hibernate를 쓰는 것과 Spring Data JPA를 쓰는 것 사이에는 큰 차이가 없습니다. 그런데도 스프링 진영에서는 Spring Data JPA를 개발했고, 사용을 권장하고 있습니다.

이렇게 한 단계  더 감싸놓은 Spring Data JPA가 등장한 이유는 크게 두가지가 있습니다.

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

먼저 '구현체 교체의 용이성'이란 Hibernate 외에 다른 구현체로 쉽게 교체하기 위함입니다.

Hibernate가 언젠가 수명이 다해 새로운 JPA구현체가 떠오를때, Spring Data JPA는 내부에서 구현체 매핑을 지원해주기 때문에 아주 쉽게 교체가 가능합니다.

다음으로 '저장소 교체의 용이성'이란 관계형 데이터베이스 외에 다른 저장소로 쉽게 교체하기 위함입니다.

관계형데이터베이스에서 다른 데이터베이스로 교체할 경우(ex MongoDB) Spring Data JPA 에서 Spring Data MongoDB로 의존성만 교체하면 됩니다.

 

 

@Getter
@NoArgsConstructor
@Entity
public class Posts {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 500, nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;

    private String author;

    @Builder
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }
}
  1. @Entity
    1. 테이블과 링크될 클래스임을 나타냄
    2. 기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍(_)으로 테이블 이름을 매칭
    3. ex) SalesManager.java -> sales_manager table
  2. @Id
    1. 해당 테이블의 PK 필드를 나타냅니다
  3. @GeneratedValue
    1. PK의 생성 규칙을 나타냄
    2. 스프링 부트 2.0에서는 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment가 됨
  4. @Column
    1. 테이블의 칼럼을 나타내며 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 칼럼이 됨
    2. 사용하는 이유는, 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용
    3. 문자열의 경우 VARCHAR(255)가 기본값, 사이즈를 500으로 늘리고 싶거나, 타입을 TEXT로 변경하고 싶은 경우에 사용
  5. @NoArgsConstructor
    1. 기본 생성자 자동 추가
    2. public Posts(){}와 같은 효과
  6. @Builder
    1. 해당 클래스의 빌더 패턴 클래스를 생성
    2. 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class PostsRepositoryTest {

    @Autowired
    PostsRepository postsRepository;

    @AfterEach
    public void cleanup(){
        postsRepository.deleteAll();
    }

    @Test
    public void getPost() {
        // given
        String title = "테스트 게시글";
        String content = "테스트 본문";

        postsRepository.save(Posts.builder().title(title).content(content).author("fmoni@gmail.com").build());

        // when
        List<Posts> postList = postsRepository.findAll();

        // then
        Posts posts = postList.get(0);
        assertThat(posts.getTitle()).isEqualTo(title);
        assertThat(posts.getContent()).isEqualTo(content);
    }
}

 

  1. @AfterEach(JUnit5)
    1. Junit에서 단위 테스트가 끝날 때마다 수행되는 메소드를 지정
    2. 보통은 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용
    3. 여러 테스트가 동시에 수행되면 테스트용 데이터베이스인 H2에 데이터가 그대로 남아 있어 다음 테스트 실행 시 테스트가 실패할 수 있음
  2. postsRepository.save()
    1. 테이블 posts에 insert/update 쿼리 실행
    2. id 값이 있다면 update, 없다면 insert가 실행
  3. postsRepository.findAll
    1. 테이블 posts에 있는 모든 데이터를 조회하는 메소드
  • 참고자료

              스프링 부트와 AWS로 혼자 구현하는 웹 서비스