SpringBoot에서 JPA 사용하기
OVERVIEW
이번 포스팅에서는 SpringBoot에서 실제로 JPA를 사용하기 위한 설정, 코드작성과 간단한 테스트를 실행해본다.
SpringBoot에 JPA 적용하기
1. 의존성 추가
우선 build.gradle
하단에 dependencies
에 위에 2줄을 추가한다.
- spring-boot-starter-data-jpa
- 스프링 부트용 Spring Data JPA 추상화 라이브러리
- 스프링 부트 버전에 맞춰 자동으로 JPA관련 라이브러리 버전을 관리해준다.
- h2
- 별도의 설치없이 프로젝트 의존성만으로 관리 가능한 인메모리 관계형 데이터베이스
- 인메모리이기 때문에 애플리케이션을 재시작 할 때 초기화되며 테스트용으로 많이 사용한다.
2. 패키지 생성
의존성을 추가하였다면 Posts라는 도메인 클래스를 생성한다.
- domain
- domain이란 소프트웨어의 요구사항 혹은 문제영역이라고 할 수 있다.
- 기존에 SQLMapper를 사용할 때 xml파일에 SQL을 작성하고 클래스에 쿼리의 결과를 담는 과정이 domain클래스에서 모두 해결된다.
3. Entity클래스 작성
Posts 클래스의 내용은 위와 같다.
내용을 하나하나 살펴보자.
- @Getter
- 필드변수의 Getter를 생성해주는 롬복 어노테이션이다.
- @NoArgsConstructor
- 매개변수 없는 생성자를 만들어주는 롬복 어노테이션이다.
- 여기서는 public Posts() {} 와 같다.
- @Entity
- 해당 클래스가 DB테이블과 매칭될 클래스라는 의미이다.
- 해당 어노테이션이 있는 클래스를 Entity클래스라고도 부른다.
- JPA를 사용하면 DB데이터에 작업을 할 때 Entity클래스를 수정하여 작업한다.
- 클래스의 카멜케이스와 테이블의 언더바를 매핑한다.
ex) SalesManager.java -> sales_manager table
- @Id
- 해당 테이블의 PK 필드를 나타낸다.
- @GeneratedValue
- PK 생성 규칙을 의미한다.
- 스프링 부트 2.0 에서는 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment가 된다.
- @Column
- 테이블의 컬럼을 나타낸다.
- Entity클래스의 필드변수들은 기본적으로 Column이 되지만 기본값 외에 추가로 변경이 필요한 옵션이 있는경우에 사용한다.
ex) 문자열의 경우 VARCHAR(255)가 기본값이지만, 사이즈를 500으로 늘리거나 타입을 TEXT로 변경하는 등의 작업을 할 때 사용한다.
- @Builder
- 해당 클래스의 빌더 패턴 클래스를 생성하는 롬복 어노테이션이다.
- 생성자 상단에 선언하면 샌성자에 포함된 필드만 빌더에 포함된다.
Posts클래스에는 Setter
가 없다.
왜 Setter를 만들지 않고 Builder패턴을 사용하는 것일까?
첫 번째 Entity클래스에 Setter가 없는 이유는 해당 클래스의 인스턴스 값들이 언제 어디서 변해야 하는지 코드상으로 명확하게 구분할 수 없기 때문이다.
Setter를 사용하지 않는 대신 해당 필드의 값 변경이 필요한 경우 명확한 목적과 의도를 나타낼 수 있는 메소드를 추가해서 사용해야 한다.
올바른예시와 잘못된 예시를 들어보자.
[잘못된 예시]
public class Order {
public void setStatus(boolean status) {
this.status = status;
}
}
public void 주문서비스_취소이벤트() {
order.setStatus(false);
}
[올바른 예시]
public class Order {
public void cancelOrder() {
this.status = false;
}
}
public void 주문서비스_취소이벤트() {
order.cancelOder();
}
이 부분을 읽으면서 개인적으로 책을 구매하기 잘했다는 생각을 했다.
잘못된 예시는 너무나도 흔히 사용하는 코드이기 때문이다.
사실 두 가지를 비교하기 전에는 잘못된 예시가 뭐가 문제지? 라는 생각이었다.
하지만 목적과 의도를 명확하게 나타내는 메소드를 만들어서 사용하는것이 얼마나 코드를 읽기 편하개 만들어주는지 알 수 있었다.
두 번째 Builder패턴을 사용하는 이유 역시 명확성을 위해서다.
Builder패턴을 사용하면 어떤 필드에 어떤 값을 넣는지 명확하게 알 수 있지만 생성자를 사용할 경우에는 어떤 필드에 어떤 값을 넣는지 명확하게 알 수 없다.
생성자를 이용하는 방법과 Builder패턴을 사용하는 경우를 비교하는 예제는 작성하지 않는다.
4. JpaRepository 작성
JpaRepository
는 Entity클래스로 Database를 접근하게 해준다.
MyBatis를 사용할 때 만드는 Dao라고 얘기하는 DB Layer 접근자와 매핑되는 개념이다.
JPA는 Interface
로 생성하며 JpaRepository<Entity 클래스, PK 타입>를 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다.
@Repository
를 별도로 추가하지 않아도 된다.
여기서 주의점은 Entity클래스와 JpaRepository는 같은 곳에 위치 해야한다는 것이다.
둘은 아주 밀접한 관계이며 Repository없이는 Entity클래스는 제 역할을 할 수 없기 때문이다.
그래서 이 둘은 Domain패키지에서 함께 관리한다.
5. H2 데이터베이스로 테스트 하기
여기까지 JPA를 사용하기 위해 의존성을 추가하고, Entity클래스와 JpaRepository를 생성하였다.
의존성 추가시에 함께 추가한 H2 데이터베이스를 이용하여 잘 동작하는지 테스트 해보자.
save
와 findAll
기능을 테스트 하는 코드다.
Junit 사용방법은 이전 포스팅을 참고하면 된다.
별다른 설정없이 @SpringBootTest
를 사용하면 H2 데이터베이스를 자동으로 실행해 준다.
여기서는 처음 사용해보는 어노테이션과 Jpa의 메소드에 대해서만 간략히 설명한다.
- @After
- Junit에서 단위 테스트가 끝날 때 마다 실행할 메소드를 지정하는 어노테이션이다.
- 보통 배포 전 전체 테스트를 수행할 때 테스트 간 데이터 침범을 막기위해 많이 사용한다.
- 여기서는 단위 테스트가 끝날 때 마다 H2 데이터 베이스를 초기화 하는데 사용하고 있다.
- postsRepository.save
- 테이블 Posts에 insert/update 쿼리를 수행한다.
- id(pk)값이 존재한다면 update, 존재하지 않는다면 insert를 수행한다.
- postsRepository.findAll
SELECT * FROM POSTS
와 동일하다.
만약 실제로 수행되는 쿼리가 궁금하다면 application.properties
에 간단한 설정을 추가하면 된다.
spring.jpa.show_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
첫 번째 설정은 실행된 쿼리문을 콘솔에 보여준다는 설정이다.
두 번째 설정은 쿼리문을 MySQL문법으로 보겠다는 설정이다.
두 번째 설정을 하지 않으면 H2 데이터베이스 문법이 적용되기 때문에 우리가 기대한 쿼리와 다른 결과가 나올 수 있으니 두 가지 설정 모두 적용하자.
SUMMARY
- Entity클래스는 실제 데이터베이스 테이블과 매핑되는 클래스이다.
- Entity클래스로 데이터베이스 접근을 가능하게 해주는것은 JpaRepository이다.
- JpaRepository는 MyBatis의 Dao(DB Layer)와 매핑되는 개념이다.
- Entity클래스와 JpaRepository는 같은 곳에 위치해야 하며 보통 Domain Package에서 함께 관리한다.
- JpaRepository는 Interface로 만들며
JpaRepository<Entity 클래스, PK 타입>를 상속하면 기본적인 CRUD메소드가 자동생성 된다. - 테스트용으로 H2 데이터베이스를 활용하며 데이터 침범이 일어나지 않도록 주의해야 한다.
Author And Source
이 문제에 관하여(SpringBoot에서 JPA 사용하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ovan/SpringBoot에서-JPA-사용하기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)