Develope Me!
[SpringBoot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - JPA 적용하기 본문
JPA에 대해 정리를 했다면 이제 실제로 적용해보도록 하자!
Spring Data JPA 적용하기
우선 build.gradle에 Spring Data JPA와 H2 데이터베이스 의존성을 추가한다.
implementation('org.springframework.boot:spring-boot-starter-data-jpa')
implementation('com.h2database:h2')
1. spring-boot-starter-data-jpa
- 스프링 부트용 Spring Data JPA 추상화 라이브러리
- 스프링부트 버전에 맞춰 자동으로 JPA 관련 라이브러리 버전 관리해줌
2. h2database
- 인메모리 관계형 데이터베이스
- 별도의 설치없이 프로젝트 의존성만으로 관리 가능
- 메모리에서 실행되기에 애플리케이션을 재시작할 때마다 초기화된다는 점에서 테스트 용도로 많이 사용
JPA 의존성을 추가해준 뒤 도메인을 담을 domain 패키지를 생성해줬다.
도메인은 소프트웨어에 대한 요구사항이나 문제영역이다.
예를 들어 쇼핑몰을 떠올린다면 회원, 장바구니, QnA, 주문 등을 떠올려볼 수 있겠다.
기존엔 Mybatis를 사용해서 xml에 쿼리문을 작성하고 클래스는 쿼리의 결과만 담았었다면 이 일들을 도메인 클래스에서 해결해준다.
이후 domain 패키지에 posts 패키지와 Entity 클래스인 Posts 클래스를 만들어줬다.
@Getter
@NoArgsConstructor
@Entity
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; //아이디
@Column(length = 500, nullable = false)
private String title; //제목 (문자열 사이즈 500, Not null)
@Column(columnDefinition = "TEXT", nullable = false)
private String content; //내용(Text 타입, Not null)
private String author; //글쓴이
@Builder
public Posts(String title, String content, String author){
this.title = title;
this.content = content;
this.author = author;
}
}
[JPA 어노테이션]
1. @Entity
- JPA가 관리하는 클래스
- JPA를 사용해서 테이블과 매핑할 것이라면 @Entity를 붙여줘야 함
2. @ID
- 해당 테이블의 PK 필드
3. @GeneratedValue
- PK 생성 규칙
- strategy = GenerationType.IDENTITY 옵션을 추가하면 PK가 auto_increment될 수 있게 함
4. @Column
- 테이블의 컬럼
- 선언하지 않더라도 해당 클래스의 필드는 모두 컬럼이 됨
- 해당 클래스의 필드에선 title의 문자열 사이즈를 500으로 늘리고 content 타입을 TEXT로 변경함
[롬복 어노테이션]
5. @NoArgsConstructor
- 기본 생성자 자동 추가 ex. public Posts(){}
6. @Getter
- 클래스 내 모든 필드의 Getter 메소드를 자동 생성
7. @Builder
- 해당 클래스의 빌더 패턴 클래스 생성
- 생성자 상단에 선언하면 생성자에 포함된 필드만 빌더에 포함
Posts 클래스에는 'Setter' 메소드가 없다는 특이점이 있다.
자바빈 규약을 생각해서 getter/setter를 모두 생성하는 경우가 있는데 이렇게 되면 해당 클래스의 인스턴스 값들이 언제 어디서 변해야 하는 지 코드상으로 명확히 구분할 수 없어 기능 변경 시에 복잡해지는 경우가 있다.
그래서 Posts 클래스와 같은 Entity 클래스에서는 절대 Setter 메소드를 만들지 않는다.
만약 해당 필드의 값 변경이 필요하다면 목적과 의도를 명확히 알 수 있는 메소드를 추가해야한다.
public class Order{
public void cancelOrder(){
this.status = false;
}
}
public void 주문서비스_취소이벤트(){
order.cancelOrder();
}
그렇다면 Setter가 없는데 어떻게 값을 채워 DB에 삽입할까?
기본적인 구조는
1. 생성자를 통해 최종 값을 채우고
2. DB에 삽입하는 것이며
값 변경이 필요한 경우엔
1. 해당 이벤트에 맞는 public 메소드를 호출해서 변경하는 것을 전제로 한다.
여기선 생성자 대신 @Builder에서 제공하는 빌더 클래스를 사용해서 생성 시점에 값을 채워주려고 한다.
//생성자
//new Example(b,a)처럼 a,b 위치 변경해도 코드 실행 전까지 문제 찾을 수 없음
public Example(String a, String b){
this.a = a;
this.b = b;
}
//빌더
//어느 필드에 어떤 값 채울지 인지 가능
Example.builder()
.a(a)
.b(b)
.build();
생성자나 빌더나 생성 시점에 값을 채운다는 점은 동일하다.
하지만 생성자의 경우엔 지금 채워야 할 필드가 무엇인지 명확히 지정할 수가 없다면
빌더의 경우엔 어느 필드에 어떤 값을 채워야 할 지 명확하게 인지할 수 있다.
이렇게 Posts 클래스를 생성한 뒤 해당 클래스를 DB에 접근하게 할 인터페이스로 JPARepository를 생성했다.
package com.study.duple.springboot.domain.posts;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostsRepository extends JpaRepository<Posts, Long> {
}
Mybatis에선 DAO를 통해 DB에 접근했다면
JPA에선
1. 인터페이스를 생성하고
2. JpaRepository<Entity 클래스, PK타입>을 상속하면
기본적인 CRUD 메소드가 자동으로 생성된다.
여기에 별도로 @Repository 어노테이션을 추가할 필요는 없고 Entity 클래스와 해당 Entity Repository를 함께 위치시켜주어야 한다.
Entity 클래스는 기본 Repository없인 제대로 역할을 할 수가 없다.
다음 포스팅은 해당 클래스의 테스트 코드를 작성해볼 것이다.
(Junit 테스트도 하고 API도 작성했지만 마우스 건전지가 나간 관계로...내일 포스팅을 해야겠다ㅜㅜ)
'Java > SpringBoot' 카테고리의 다른 글
[SpringBoot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - API 구현 (0) | 2022.02.23 |
---|---|
[SpringBoot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - JPA 테스트 코드와 스프링 웹 계층 (0) | 2022.02.21 |
[SpringBoot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - JPA 소개 (0) | 2022.02.19 |
[SpringBoot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 테스트코드 (0) | 2022.02.16 |
[SpringBoot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 개발 환경 세팅 (0) | 2022.02.15 |