엔티티 간 연관 관계 매핑의 핵심 개념
하이버네이트는 객체 관계 매핑(ORM)을 통해 데이터베이스와 자바 객체 사이의 연결을 제공하며, 특히 엔티티 간의 관계를 정의하는 기능이 핵심입니다. 대표적인 관계 유형으로는 OneToOne, OneToMany, ManyToOne, ManyToMany 등이 있으며, 이들 관계에 대해 cascade 속성을 설정함으로써 연관된 엔티티에 대한 동작을 제어할 수 있습니다.
cascade 옵션의 의미
CascadeType은 다음과 같은 동작을 지정할 수 있습니다:
- PERSIST: 부모 엔티티 저장 시 자식 엔티티도 함께 저장됨
- MERGE: 병합 시 자식 엔티티도 반영됨
- REMOVE: 삭제 시 관련 자식 엔티티도 삭제됨
- REFRESH: 업데이트 시 자식 정보도 새로 고침됨
- DETACH: 세션에서 분리될 때 자식도 함께 분리됨
- ALL: 위 모든 동작을 포함
예시: 반 클래스와 학생 엔티티
@Entity
@Table(name = "tb_class")
@Data
public class ClassEntity {
@Id
private String id;
@Column
private String className;
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.LAZY)
private List<Student> enrolledStudents;
}
@Entity
@Data
public class Student {
@Id
private String studentId;
@Column
private String studentName;
@Column
private Integer age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "class_id", nullable = false)
private ClassEntity enrolledClass;
}
주의사항: cascade 사용의 현실성
실제 개발 현장에서는 하이버네이트의 cascade 기능보다는 수동 처리가 더 바람직합니다. 이유는 다음과 같습니다:
- 코드의 흐름이 명확해지고, 로직의 의도가 직관적으로 드러남
- 급격한 데이터 일관성 문제(예: 자식 삭제 실패 시 부모 삭제도 취소)를 방지 가능
- 테스트 및 디버깅이 쉬워짐
- 성능 최적화가 용이 (예: 배치 처리, 트랜잭션 범위 조절)
따라서 기본 설정인 cascade = {} 또는 cascade = CascadeType.NONE을 유지하고, 비즈니스 로직 내에서 명시적으로 저장/삭제 순서를 관리하는 것이 권장됩니다.
결론
하이버네이트의 연관 관계 매핑은 강력한 도구지만, 과도한 자동화보다는 제어 가능한 코드 기반 처리가 장기적으로 유지보수성과 신뢰성을 높입니다. 관계 매핑은 설계 단계에서 충분히 고려해야 하지만, 실행 시점의 행동은 명시적으로 제어하는 것이 이상적입니다.