JPA의 Entity Manager
- 영속성 컨텍스트(Persistence Context)를 두어 Entity를 관리하는 주체
- @PersistenceContext 어노테이션을 통해 주입하거나 생성자 주입을 했을 시 자동적으로 주입 됨
import org.springframework.stereotype.Service
import jakarta.persistence.EntityManager
import jakarta.persistence.PersistenceContext
@Service
class MyService {
@PersistenceContext
private lateinit var entityManager: EntityManager
}
- EntityManager는 여러 종류의 함수를 지원하여, Entity의 상태를 변경
- persist() : Entity를 영속성 컨텍스트에 추가
- merge() : Detached 상태의 Entity를 다시 영속성 컨텍스트에 추가, 변경이 감지되도록 함
- remove() : Entity를 삭제
- detach() : 영속성 컨텍스트에서 Entity를 분리, Detached 상태로 만듦
- clear() : 영속성 컨텍스트를 초기화, 모든 Entity를 Detached 상태로 만듦
- close() : EntityManager를 종료
- flush() : 영속성 컨텍스트 내 변경된 Entity를 감지, DB와 동기화
- find() : 주어진 Entity의 PK를 이용, Entity를 DB에서 조회, 영속성 컨텍스트에 추가
Spring Data JPA의 Repository
Spring Data JPA는 다음과 같은 Repository 인터페이스를 제공
- CrudRepository는 기본적인 DB 대상 CRUD를 위한 method를 제공
- PagingAndSortingRepository는 CrudRepository를 상속받아 기본 CRUD에 더해 페이징 및 정렬 기능 제공
- JPARepository는 PagingAndSortingRepository를 상속받아 부가적인 기능을 추가로 제공
JPA 인터페이스 정의
interface PostRepository: JpaRepository<Post, Long> {}
Entity 작성 전 설정
- Entity는 Entity Manager를 통해 상태가 변경되기도 하고 자체적으로 도메인의 요구사항을 갖기도 하므로 Data Class 보다 일반 Class가 적합
- Hibernate에서는 지연로딩을 위한 Proxy를 설정하기 위해 Entity 클래스를 상속받아 사용
- Kotlin에서 기본적으로 class는 Java로 변환시 final(immutable 형태)로 컴파일 되므로 open class 형태로 선언해야 하며 NoArgsConstructor가 필요
- 플러그인(allopen, noarg)을 사용하면 위 설정(open class, NoArgsConstructor)을 직접하지 않아도 됨
- allopen의 경우 plugin.spring에 포함되어 있음
plugins {
kotlin("plugin.noarg") version "1.8.22"
}
- Entity 관련 클래스들에 allopen, noarg 적용
noArg {
annotation("jakarta.persistence.Entity")
annotation("jakarta.persistence.MappedSuperclass")
annotation("jakarta.persistence.Embeddable")
}
allOpen {
annotation("jakarta.persistence.Entity")
annotation("jakarta.persistence.MappedSuperclass")
annotation("jakarta.persistence.Embeddable")
}
- MappedSuperclass : 객체입장에서 상속이 필요할 때 사용
- Embeddable : Table로 인식되진 않지만 하나의 객체로 표현, Entity 내부에서 사용하고 싶을 때 사용하는 어노테이션으로 VO(Value Object) 같은 형태, 이를 사용하는 측에 @Embedded를 표시
Entity 간 관계 연결
- 관계는 양방향과 단방향이 존재
- DB 내 테이블은 기본적으로 양방향 관계, JOIN을 통해 두 테이블을 참조할 수 있기 때문
- 관계 설정은 @OneToMay, @ManyToOne, @OneToOne으로 설정(@ManyToMany도 있지만 사용 X)
- M:N 관계는 테이블 관점에서 1:N 관계와 N:1 관계로 이루어진 세 테이블과 동일
- JPA를 통해서 직접 테이블 생성 시 @ManyToMany를 사용할 수 있지만 중간의 N에 해당하는 테이블은 객체 상으로 표현되지 않기 때문에 의도치 않은 쿼리가 만들어질 수 있음(Mapping 정보만 넣을 수 있음, 추가 정보 X)
@OneToMany(mappedBy = "연관관계의 주인이 관계를 참조하는데 사용하는 멤버변수명")
- mappedBy : 연관관계의 소유 주체가 누구인지를 JPA에 알려줌
- 단방향 관계일 때는 필요 X, 양방향 관계일 때는 필요
- JPA는 서로 관계가 있다는 것은 알지만 FK를 누가 소유하고 있는지 모르기 때문
- 1:N 관계에서 보통 N쪽이 연관관계의 주인으로 1쪽에 mappedBy를 설정을 하여 연관관계의 주인을 JPA에 알려줌
@JoinColumn : 명시적으로 외래키가 무엇인지 JPA에 알려줌(JPA로 테이블을 직접 생성 해주는 경우 필요 X)
'TIL(Today I Learned)' 카테고리의 다른 글
TIL - SQL WITH 재귀 쿼리 (0) | 2024.05.14 |
---|---|
TIL - 댓글을 가져올 때 순환 참조 발생 (0) | 2024.05.13 |
JPA(Java Persistence API)의 이해 1 (0) | 2024.05.09 |
TIL - 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기 (0) | 2024.05.08 |
Baekjoon 구간 합 구하기 4 문제를 풀면서 삽질하기 (1) | 2024.05.02 |