JPA(Java Persistence API)
- ORM의 한 종류, Java 및 Kotlin의 객체를 사용해 DB를 쉽게 조회, 조작할 수 있도록 해 줌
ORM(Object-Relational Mapping)
- 객체와 관계형 DB 간의 매핑을 담당
- 별도의 SQL 쿼리를 작성하지 않아도 객체를 DB에 저장 및 조회 가능
- 객체를 활용하므로 객체 지향 프로그램 가능 및 재사용성 증대
- DB에 종속적이지 않음(DB 변경 시 코드 최소화)
- 필요에 따라 데이터를 캐싱하므로 효율적인 데이터 조회 가능
- ORM 개념 학습 러닝 커브 有
- 복잡한 쿼리나 특수한 DB 기능을 사용하는 경우 직접 SQL 작성이 효율적
JDBC, Hibernate, JPA, Spring Data JPA
- JDBC(Java Database Connectivity)
- Java 애플리케이션에서 DB에 접근, 각종 SQL을 사용할 수 있게 해 줌
- JDBC API, JDBC Driver로 구성
- JDBC API는 Interface, JDBC Driver는 Interface의 DB별 구현체
- 사용자는 Driver 설정만으로 동일 Interface를 통해 다른 DB 사용 가능
- JPA(Java Persistence API)
- JDBC API를 내부적으로 사용
- SQL을 직접 사용하기보다 객체지향적으로 DB를 다룰 수 있도록 하는 역할을 하는 ORM
- Hibernate
- JPA Interface의 구현체 중 하나로 대표적으로 많이 사용
- 내부적으로 JDBC API 사용
- Spring Data JPA
- JPA를 쓰기 편하게 만들어 놓은 라이브러리
- JPA를 한 단계 더 추상화시킨 Repository라는 인터페이스를 제공
- Repository의 구현체는 내부적으로 JPA를 사용
JPA의 Entity
- 테이블과 맵핑되는 객체
- 다음 코드처럼 클래스 상단에 @Entity 어노테이션을 붙이면 JPA에서 관리하는 객체로 작동함
@Entity
@Table(name = "post")
class Post(
@Column(name = "title")
var title: String,
// ...
@OneToMany(mappedBy = "post")
val comments: List<Comment> = mutableListOf(),
@ManyToOne
@JoinColumn(name = "author_id", nullable = false)
val author: User,
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
}
- @Entity : Java 객체로 맵핑
- @Table : 관계있는 테이블을 명시하며 생략 가능(생략 시 JPA는 Entity 클래스명을 이름으로 사용, 테이블 자동 맵핑)
- @Id : Entity의 PK(Primary Key)를 지정
- @GeneratedValue : 자동으로 생성되는 식별자 사용
- @Column : DB 컬럼과 맵핑
- @ManyToOne, @OneToMany, @OneToOne, @ManyToMany : 객체 간 관계 설정
JPA의 Persistence Context
- Persistence Context에 Entity 포함 유무에 따라 DB에 변경사항을 저장하여 영속성 부여 여부를 결정
- 예) 한 트랜잭션 안에서 데이터를 DB로부터 가져올 때 이 데이터는 Persistence Context에 포함된 상태이며 변경된 값은 트랜잭션이 끝날 때 DB에 반영
JPA는 Persistence Context 개념 활용, 아래 역할들을 수행
- Entity의 상태 추적
- Persistence Context는 Entity가 Transient(New), Managed, Detached, Removed 등의 상태에 있는지 추적
- JPA는 다음 Entity의 상태를 통해 트랜잭션 종료 시 DB에 최종적으로 어떤 쿼리를 보낼지 결정
- 트랜잭션이 끝나는 시점에 Managed, Removed 상태의 Entity들의 변경사항이 DB에 반영됨
- Transient : 아직 Persistence Context에 포함되지 않은 새로운 Entity 상태
- Managed : Persistence Context에 저장된 상태
- Detached : Persistence Context에 저장되었다가 분리된 상태
- Removed : 삭제된 상태
- 캐싱(Caching)
- Persistence Context 내 Entity를 Map 형태로 임시 저장
- 동일한 Entity 조회 시 DB를 직접 조회하지 않고 해당 Entity를 사용할 수 있게 해 줌
- 지연 로딩(Lazy Loading) 및 즉시 로딩(Eager Loading)
- 연관관계에 있는 Entity를 지연로딩하거나 즉시 로딩할 수 있는 기능을 제공
- 지연 로딩 : 연관된 Entity가 실제 필요한 시점에 DB에서 로드할 수 있도록 함
- 즉시 로딩 : 연관된 Entity에 접근하는 순간 쿼리가 수행됨
- 트랜잭션(Transaction)을 통한 쓰기 지연
- 코드 상에서 변경한 Entity를 바로 반영하지 않음
- Entity의 상태 변경을 통해 SQL 저장소에 쿼리를 저장
- 최종적으로 트랜잭션이 종료되는 시점(commit) 이전에 DB에 모아둔 쿼리를 보내 DB와 영속성 컨텍스트를 동기화
- commit 종료 이전 쿼리를 보내 동기화하는 것을 flush라고 함
- flush로 전송된 쿼리는 rollback이 가능, commit 완료 후에는 트랜잭션이 끝나므로 rollback 불가
- Dirty Checking
- Entity의 변경 사항을 추적하는 과정
- Dirty Checking은 Entity가 영속성 컨텍스트에 저장된 상태(Managed)에 대해서만 수행됨
'TIL(Today I Learned)' 카테고리의 다른 글
TIL - 댓글을 가져올 때 순환 참조 발생 (0) | 2024.05.13 |
---|---|
JPA(Java Persistence API)의 이해 2 (0) | 2024.05.10 |
TIL - 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기 (0) | 2024.05.08 |
Baekjoon 구간 합 구하기 4 문제를 풀면서 삽질하기 (1) | 2024.05.02 |
숫자 야구 게임을 구현하면서 다시 객체 지옥에 빠지다. (1) | 2024.05.01 |