멋쟁이사자처럼 13기/정기 세션

[멋사/Mac OS] 5주차 정기 세션 (Part 4. 영속성 전이 ~ Part 6. Auditing)

개발자 지망생 리네 2025. 6. 20. 23:04

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;
}