# CASCADE
- 부모 엔티티에서 자식 엔티티로 상태를 전이하는 것
ex. 부모 엔티티 저장할 때 자식 엔티티도 함께 저장, 게시글과 첨부파일
- Parent와 Child가 라이프사이클이 동일할 때, Child를 소유하는 Parent가 하나일 때 사용하는 것이 좋음
# CascadeType
ALL - 엔티티의 모든 상태 전이
PERSIST - 엔티티 persiste(영속) 전이
REMOVE - 삭제 전이
MERGE - merge 전이
REFRESH - refresh 전이
DETACH - detach 전이
[Hibernate ORM 6.0.0 User Guide 예제 코드]
@Entity
public class Person {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
private List<Phone> phones = new ArrayList<>();
//Getters and setters are omitted for brevity
public void addPhone(Phone phone) {
this.phones.add(phone);
phone.setOwner(this);
}
}
@Entity
public class Phone {
@Id
private Long id;
@Column(name = "`number`")
private String number;
@ManyToOne(fetch = FetchType.LAZY)
private Person owner;
//Getters and setters are omitted for brevity
}
# 고아 객체
- 부모 엔티티와 연관관계가 끊어진 자식 엔티티 자동으로 삭제
- orphanRemoval = true
- 부모 엔티티에서 자식엔티티 list에서 remove를 한 경우
phones.remove(phone);
- ★특정 엔티티가 개인 소유할때만 (Child를 소유하는 Parent가 하나일 때) orphanRemoval = true 로 사용 ★
[Hibernate ORM 6.0.0 User Guide 예제 코드]
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Phone> phones = new ArrayList<>();
//Getters and setters are omitted for brevity
public void addPhone(Phone phone) {
phones.add(phone);
phone.setPerson(this);
}
public void removePhone(Phone phone) {
phones.remove(phone);
phone.setPerson(null);
}
}
@Entity(name = "Phone")
public static class Phone {
@Id
@GeneratedValue
private Long id;
@NaturalId
@Column(name = "`number`", unique = true)
private String number;
@ManyToOne
private Person person;
//Getters and setters are omitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Phone phone = (Phone) o;
return Objects.equals(number, phone.number);
}
@Override
public int hashCode() {
return Objects.hash(number);
}
}
# cascade = CascadeType.ALL + orpahnRemoval = true
- 두 옵션을 모두 활성화하면 부모 엔티티를 통해서 자식 엔티티의 생명주기 관리 가능
- 도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용
- 부모 엔티티 삭제 시 자식 엔티티들도 삭제됨
# cascade = CascadeType.ALL, cascade = CascadeType.REMOVE
- 부모 엔티티 삭제 시 자식 엔티티들도 삭제됨
- orpahnRemoval=true 없어도 연관관계 상태(삭제)까지 전파됨
- orpahnRemoval=true 없으므로 부모 엔티티에서 가져온 자식 엔티티 리스트에서 remove할 경우 자식 엔티티가 삭제되는건 아님!
# cascade = CascadeType.PERSIST
- 부모 엔티티 삭제 시 부모 엔티티만 삭제
- 부모 자식을 바라보는 자식 엔티티가 있을 경우 FK 제약이 때문에 에러 발생
ERROR: Referential integrity constraint violation: "FKLH67J1N7X7GT59U0PBKWQH6O6: PUBLIC.CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.PARENT(ID) (CAST(1 AS BIGINT))"; SQL statement:
# cascade = CascadeType.PERSIST + orpahnRemoval = true
- 부모 엔티티 삭제 시 자식 엔티티들도 삭제됨
- orpahnRemoval=true 있어야 자식 삭제됨
인프런 - 자바 ORM 표준 JPA 프로그래밍 - 기본편(김영한 강사님) 강의를 수강하며 정리한 글입니다 :)
'개발 > JPA' 카테고리의 다른 글
[JPA] JPQL fetch join / 연관된 entity 한번에 select / distinct로 엔티티 중복 제거 / fetch join 페이징 안 될 때 @BatchSize 설정 (0) | 2022.04.12 |
---|---|
[JPA] Hibernate Query Language(HQL) Projection / 하이버네이트 쿼리 언어 프로젝션 조회 / 특정 컬럼만 조회 / 예문 (0) | 2022.04.11 |
[JPA] 지연 로딩 LAZY , 즉시 로딩 EAGER (0) | 2022.04.06 |
[JPA] 프록시 (0) | 2022.04.06 |
[JPA] 상속관계 매핑 - 상속 전략 (0) | 2022.04.06 |
댓글