[JPA] JPA 세팅, h2(인메모리 관계형 데이터 베이스), 어노테이션정리
build.gradle에 의존성 등록 (dependencies 에 추가)
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('com.h2database:h2')spring-boot-starter-data-jpa
스프링부트용 Spring Data Jpa 추상화 라이브러리
스프링부트버전에 맞춰서 자동으로 JPA 관련 라이브러리들의 버전을 관리해 줌
h2
인메모리 관계형 데이터 베이스
별도의 설치가 필요없이 프로젝트 의존성만으로 관리가능
메모리에서 실행되기 때문에 재시작할때마다 초기화된다. 그래서 테스트 용도로 많이사용
JPA 예제
Entity클래스 (Posts.java)
package com.anse.book.springboot.domain.posts;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
/*
* @Entity
* - 테이블과 링크될 클래스임을 나타낸다
* - 카멜케이스이름을 언더스코어 네이밍으로 테이블 이름을 매칭
* ex) SaleManager.java -> sales_manager (table)
*
* @NoArgsConstructor
* - 롬복의 어노테이션으로 기본 생성자 자동 추가
*
* @Getter
* - 모든 필드의 Getter 메서드 생성
*/
public class Posts {
/*
@ Id
- 해당 테이블의 PK
@GeneratiedValue
- PK의 생성 규칙
- GenerationType.IDENTITY를 추가해야만 auto_increment가 된다
@Column
- 테이블의 컬럼을 나타내며, 굳이 선언하지 않아도 해당클래스의 필드는 모두 컬럼이 된다.
- 사용하는 이유는, 기본값 외에 추가로 변경이 필요한 옵션이 있을때 사용
- 문자열은 VARCHAR(255)가 기본값이지만,
사이즈를 늘리거나 (length=500)
타입을 텍스트로 변경(ex:content)하고 싶을 때 사용 (columnDefinition="TEXT")
*/
strategy= GenerationType.IDENTITY) (
private Long id;
length=500, nullable=false) (
private String title;
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;
}
}
Entity 클래스에는 절대 Setter를 만들지 않는다.
해당 필드의 값 변경이 필요하면 명확히 그 목적과 의도를 나타낼 수 있는 메서드를 추가해야 한다.
@Builder 를 통해 최종값을 채운 후 DB에 삽입
생성자나 빌더나 역할은 같지만, 빌더는 어떤 필드에 어떤 값을 채워야 할 지 명확하게 인지할 수 있다
// 생성자 (new Example(b,a)) 로 실수하면 실행전까지 문제 못찾는다
public Example(String a, String b) {
this.a = a;
this.b = b;
}
// 빌더 (명확하다)
Example.builder()
.a(a)
.b(b)
.build();
JapRepository 생성 ( DB에 접근하게 해줄 PostsRepository 인터페이스)
package com.anse.book.springboot.domain.posts;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostsRepository extends JpaRepository<Posts,Long> {
}ibatis 나 MyBatis에서는 Dao 라고 불리는게 JPA에서는 Repository라 부른다
단순히 인터페이스 생성후, JpaRepository<Entity 클래스, PK타입> 을 상속하면 CRUD메서드가 자동 생성된다
@Repository를 추가할 필요도 없다
주의할 점은 Entity 클래스와동일한 위치에 있어야 한다.
JPA 테스트 ( save, findAll 기능 )
package com.anse.book.springboot.domain.posts;
import org.junit.After;
import org.junit.Assert;
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;
/*
@SpringBootTest
-별도의 설정없이 H2 데이터베이스를 자동을 실행시켜줌
*/
SpringRunner.class) (
public class PostsRepositoryTest {
PostsRepository postsRepository;
/*
@After
- Junit에서 단위테스트가 끝날때마다 수행되는 메서드
*/
public void cleanup() {
postsRepository.deleteAll();
}
public void 게시글저장_불러오기() {
//given
String title = "테스트 게시글";
String content = "테스트 본문";
/*
테이블 posts에 insert/update 쿼리를 실행
id가 있으면 update , 없으면 insert
*/
postsRepository.save(Posts.builder()
.title(title)
.content(content)
.author("anse@gmail.com")
.build()
);
//when
/*
테이블 posts에 있는 모든 데이터 조회
*/
List<Posts> postsList = postsRepository.findAll();
//then
Posts posts = postsList.get(0);
assertThat(posts.getTitle()).isEqualTo(title);
assertThat(posts.getContent()).isEqualTo(content);
}
}
@Entity
테이블과 링크될 클래스임을 나타냄
카멜케이스이름을 언더스코어 네이밍으로 테이블 이름 매칭
ex) SaleManager.java -> sales_mansger
@NoArgsConstructor
롬복의 어노테이션으로 기본 생성자 자동으로 생성
@Id
해당 테이블의 PK
@GeneratedValue
PK의 생성규칙
GenerationType.IDENTITY를 추가해야만 auto_increment가 됨
@Column
테이블의 컬럼 (굳이 안써도 해당클래스의 필드는 모두 컬럼이 된다)
사용하는 이유는, 기본값 외에 추가로 변경이 필요한 옵션이 있을때
ex)문자열의 기본은 VARCHAR(255) 이지만 사이즈를 늘리고 싶거나 (length=500)
ex)타입을 텍스트로 변경하고 싶을때 (columnDefinition="TEXT")
@Builder
롬복 어노테이션, 해당 클래스의 빌더 패턴 클래스를 생성
생성자 상단에 선언시 생성자에 포함된 필드만 빌더에 포함