139 lines
6.2 KiB
Markdown
139 lines
6.2 KiB
Markdown
아래는 "JPA 생명주기와 영속성 컨텍스트"에 대해 설명하는 글입니다. 예시를 포함하되, 롬복은 사용하지 않고 명확한 이해를 돕기 위해 기본적인 코드 스타일을 유지했습니다.
|
|
|
|
---
|
|
|
|
### JPA 생명주기와 영속성 컨텍스트
|
|
|
|
JPA에서 엔티티는 특정한 생명주기를 거치며 관리됩니다. 이 생명주기는 영속성 컨텍스트(Persistence Context)라는 JPA의 핵심 개념과 밀접하게 연관되어 있습니다. 영속성 컨텍스트는 엔티티의 상태를 추적하고 관리하며, 데이터베이스와의 동기화를 담당하는 환경입니다. 이를 통해 JPA는 객체와 데이터베이스 간의 매핑을 효율적으로 처리합니다.
|
|
|
|
#### 영속성 컨텍스트란?
|
|
영속성 컨텍스트는 엔티티 매니저(EntityManager)가 엔티티를 관리하는 논리적인 공간입니다. 엔티티가 영속성 컨텍스트에 포함되면 JPA가 해당 엔티티의 상태를 추적하고, 트랜잭션이 커밋될 때 데이터베이스에 반영합니다. 주요 특징은 다음과 같습니다:
|
|
- **1차 캐시**: 조회한 엔티티를 메모리에 저장해 동일 트랜잭션 내에서 재사용 가능.
|
|
- **변경 감지(Dirty Checking)**: 엔티티의 변경 사항을 자동으로 감지해 SQL을 생성.
|
|
- **쓰기 지연(Write Behind)**: 트랜잭션 커밋 시점에 변경 사항을 한꺼번에 데이터베이스에 반영.
|
|
|
|
#### 엔티티 생명주기
|
|
엔티티는 네 가지 상태를 거칩니다:
|
|
1. **비영속(Transient)**
|
|
- 엔티티 객체가 생성되었지만, 영속성 컨텍스트나 데이터베이스와 연결되지 않은 상태.
|
|
- JPA가 전혀 관리하지 않음.
|
|
2. **영속(Managed)**
|
|
- 영속성 컨텍스트에 의해 관리되는 상태.
|
|
- `persist()`나 `find()` 메서드로 엔티티가 영속성 컨텍스트에 포함됨.
|
|
3. **준영속(Detached)**
|
|
- 영속성 컨텍스트에서 분리된 상태.
|
|
- `detach()`나 `close()`로 인해 더 이상 관리되지 않음.
|
|
4. **삭제(Removed)**
|
|
- 영속성 컨텍스트와 데이터베이스에서 삭제되도록 예약된 상태.
|
|
- `remove()` 호출 후 트랜잭션 커밋 시 삭제됨.
|
|
|
|
#### 생명주기 예시
|
|
아래는 `Book` 엔티티를 통해 생명주기를 설명하는 코드입니다.
|
|
|
|
```java
|
|
import jakarta.persistence.Entity;
|
|
import jakarta.persistence.Id;
|
|
|
|
@Entity
|
|
public class Book {
|
|
@Id
|
|
private Long id;
|
|
private String title;
|
|
|
|
public Book() {} // JPA 기본 생성자 요구
|
|
|
|
public Book(Long id, String title) {
|
|
this.id = id;
|
|
this.title = title;
|
|
}
|
|
|
|
public Long getId() { return id; }
|
|
public void setId(Long id) { this.id = id; }
|
|
public String getTitle() { return title; }
|
|
public void setTitle(String title) { this.title = title; }
|
|
}
|
|
```
|
|
|
|
```java
|
|
import jakarta.persistence.EntityManager;
|
|
import jakarta.persistence.EntityManagerFactory;
|
|
import jakarta.persistence.Persistence;
|
|
|
|
public class JpaLifecycleExample {
|
|
public static void main(String[] args) {
|
|
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaExample");
|
|
EntityManager em = emf.createEntityManager();
|
|
em.getTransaction().begin();
|
|
|
|
// 1. 비영속 상태
|
|
Book book = new Book(1L, "JPA 기초");
|
|
System.out.println("상태: 비영속");
|
|
|
|
// 2. 영속 상태
|
|
em.persist(book);
|
|
System.out.println("상태: 영속");
|
|
|
|
// 영속성 컨텍스트에서 동일 객체 재사용 (1차 캐시)
|
|
Book foundBook = em.find(Book.class, 1L);
|
|
System.out.println("동일 객체: " + (book == foundBook)); // true
|
|
|
|
// 변경 감지
|
|
book.setTitle("JPA 심화"); // 별도 update 호출 없이 변경 감지됨
|
|
|
|
// 3. 삭제 상태
|
|
em.remove(book);
|
|
System.out.println("상태: 삭제 예약");
|
|
|
|
// 트랜잭션 커밋 - 데이터베이스 반영
|
|
em.getTransaction().commit();
|
|
System.out.println("커밋 완료");
|
|
|
|
// 4. 준영속 상태
|
|
em.detach(book); // 이미 삭제되었으므로 효과 없음
|
|
em.close();
|
|
|
|
// 새로운 트랜잭션에서 준영속 상태 확인
|
|
EntityManager em2 = emf.createEntityManager();
|
|
em2.getTransaction().begin();
|
|
book.setTitle("JPA 고급"); // 영속성 컨텍스트가 없으므로 반영 안 됨
|
|
em2.getTransaction().commit();
|
|
em2.close();
|
|
|
|
emf.close();
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 코드 설명
|
|
1. **비영속 상태**
|
|
- `Book book = new Book(1L, "JPA 기초");`: 객체는 생성되었지만 JPA와 무관합니다.
|
|
|
|
2. **영속 상태**
|
|
- `em.persist(book)`: 영속성 컨텍스트에 포함되며, 1차 캐시에 저장됩니다.
|
|
- `em.find(Book.class, 1L)`: 데이터베이스 조회 없이 캐시에서 반환됩니다.
|
|
|
|
3. **변경 감지**
|
|
- `book.setTitle("JPA 심화")`: 영속 상태의 엔티티는 변경이 감지되어 커밋 시 자동으로 `UPDATE` 쿼리가 실행됩니다.
|
|
|
|
4. **삭제 상태**
|
|
- `em.remove(book)`: 엔티티가 삭제 예약되며, 커밋 시 `DELETE` 쿼리가 실행됩니다.
|
|
|
|
5. **준영속 상태**
|
|
- `em.detach(book)` 또는 `em.close()`: 영속성 컨텍스트에서 분리되어 더 이상 관리되지 않습니다.
|
|
|
|
#### 영속성 컨텍스트의 이점
|
|
- **성능 향상**: 1차 캐시로 동일 트랜잭션 내 반복 조회를 줄임.
|
|
- **자동 동기화**: 변경 감지로 개발자가 직접 SQL을 작성할 필요 없음.
|
|
- **트랜잭션 보장**: 쓰기 지연으로 트랜잭션 내 변경을 일괄 처리.
|
|
|
|
#### 주의사항
|
|
- 영속성 컨텍스트는 트랜잭션 범위에 따라 생명주기가 달라집니다. 트랜잭션이 끝나면 컨텍스트도 종료됩니다(기본적으로).
|
|
- 준영속 상태의 엔티티는 변경 감지가 적용되지 않으므로, 필요 시 `merge()`로 다시 영속 상태로 전환해야 합니다.
|
|
|
|
---
|
|
|
|
JPA의 생명주기와 영속성 컨텍스트는 엔티티 관리의 핵심입니다. 이를 이해하면 데이터베이스 작업을 더 효율적으로 처리할 수 있습니다. 다음 장에서는 트랜잭션 관리와 실무 활용을 다뤄보겠습니다.
|
|
|
|
---
|
|
|
|
책의 흐름에 맞는지, 추가 예시나 설명이 필요하면 말씀해 주세요! |