본문 바로가기
개발/JPA

[JPA] 연관관계 영속성 전이 CASCADE

by Allonsy 2022. 4. 7.
반응형

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

 

 

Hibernate ORM 6.0.0.Final User Guide

Fetching, essentially, is the process of grabbing data from the database and making it available to the application. Tuning how an application does fetching is one of the biggest factors in determining how an application will perform. Fetching too much dat

docs.jboss.org

 

# 고아 객체

- 부모 엔티티와 연관관계가 끊어진 자식 엔티티 자동으로 삭제

- 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 프로그래밍 - 기본편(김영한 강사님) 강의를 수강하며 정리한 글입니다 :)

반응형

댓글