4. 영속성 전이
(1) 영속성 전이
- 영속성 전이 : 엔티티의 상태를 변경할 때 해당 엔티티와 연관된 엔티티의 상태 변화를 전파해주는 기능
- 부모 엔티티 상태 변경 -> 자식 엔티티 상태 자동 변경
영속성 전이 조건
1. 자식 엔티티가 독립적으로 존재하지 않고 부모 엔티티에 완전히 의존적일 때
2. 부모가 저장되면 자식도 같이 저장, 부모가 삭제되면 자식도 같이 삭제 (유사한 라이프 사이클)
(2) Cascade
- Cascade: 부모 엔티티의 상태 변화가 자식 엔티티에도 자동으로 전파 (부모의 생명주기에 자식도 함께 묶음)
| PERSIST | REMOVE | MERGE | REFRESH | ALL |
| 부모 저장 시 자식 저장 | 부모 삭제 시 자식 삭제 | 부모 변경 시 자식 변경 | 부모 새로고침 시 자식도 새로고침 | 모든 옵션 포함 |
- 예시 코드
@Entity
@Table(name = "orders")
@Getter
public class Order {
@Id @GeneratedValue
private Long id;
// 양방향 매핑
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItemList = new ArrayList<>();
public void addOrderItem(OrderItem orderItem) {
orderItemList.add(orderItem); // Order의 자식에 item을 넣음 Order -> OrderItem
orderItem.setOrder(this); // OrderItem의 Order에 넣음 OrderItem -> Order
}
}
(3) orphanRemoval
- 고아 객체 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티
- 영속성 전이 기능과 같이 사용하면 부모 엔티티를 통해 자식의 생명 주기를 관리할 수 있음
- 참조하고 있는 곳이 하나일 때만 사용 (@OneToOne, @OneToMany)
- 고아 객체 제거 기능 활성화
public class Order {
// (생략)
@OneToMany(mappedBy = "order", cascade=CascadeType.ALL, orphanRemoval = true)
private list<OrderItem> orderItems = new ArrayList<>();
}
5. Fetch 전략 (즉시 vs 지연 로딩)
- Fetch 전략 : JPA에서 연관된 엔티티를 조회할 때, 언제 해당 엔티티를 함께 조회할 지를 결정
| 즉시 로딩 (EAGER) | 지연 로딩 (LAZY) | |
| 정의 | 조회 시 연관된 엔티티를 join 쿼리로 한 번에 불러옴 | 연관된 엔티티를 실제로 사용할 때까지 로딩을 미룸 |
| 특징 | 엔티티 조회 시, 연관된 엔티티도 즉시 로딩 | 프록시 객체로 존재하다가 실제 접근 시점에 SELECT 쿼리 실행 |
| 기본 설정 | @ManyToOne, @OneToOne | @OneToMany, @ManyToMany |
| 장점 | - 필요한 시점에만 데이터를 불러와 성능 최적화 가능 - 쿼리의 단순화 |
- 코드 접근 시 N+1 문제 없이 데이터를 사용할 수 있음 |
| 단점 | - 초기에는 프록시 객체만 들어있어서 잘못 다루면 LazyInitializationException 발생 가능 - 트랜잭션 밖에서 접근하면 에러 발생 가능 |
- 불필요한 데이터까지 함께 로딩되어 성능 저하 가능 - 연관 관계가 복잡해지면 쿼리 수가 많아지고 join으로 인해 속도 저하 발생 |
- 예시 코드 (즉시 로딩)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "member_id")
private Member member;
- 예시 코드 (지연 로딩)
@OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
private List<OrderItem> orderItems;
-> OrderItem 클래스에 있는 order 필드가 연관관계의 주인
6. Auditing
- Auditing : 데이터베이스의 테이블에 시간에 대해 자동으로 값을 넣어주는 기능
| @MappedSuperclass | 자식 엔티티에 공통 필드를 상속하기 위한 JPA 상속 설정 |
| @EntityListeners | 엔티티의 생명주기를 감지할 리스너 등록 |
| AuditingEntityListener | 생성, 수정 시점을 자동으로 기록해주는 리스너 클래스 |
| @CreateDate | 엔티티가 최초 저장될 때 시간 자동 기록 |
| @LastModifiedDate | 엔티티가 수정될 때마다 시간 자동 갱신 |
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AuditingClass {
// 등록 날짜
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_date", nullable = false, updatable = false)
@CreatedDate
private Date createdDate;
// 수정 날짜
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modified_time", nullable = false)
@LastModifiedDate
private Date createdDate;
}'멋쟁이사자처럼 13기 > 정기 세션' 카테고리의 다른 글
| [멋사/Mac OS] 5주차 정기 세션 (Part 3. QueryDSL 소개 및 JPQL과 비교) (0) | 2025.06.20 |
|---|---|
| [멋사/Mac OS] 5주차 정기 세션 (Part 2. JPA 쿼리 작성 방법) (0) | 2025.06.20 |
| [멋사/Mac OS] 5주차 정기 세션 (Part 1. 실습환경 세팅) (0) | 2025.06.20 |
| [멋사/Mac OS] 4주차 정기 세션 (Part 3. 실습) (0) | 2025.06.18 |
| [멋사/Mac OS] 4주차 정기 세션 (Part 2. 엔티티 설계) (0) | 2025.06.18 |