[JPA] 영속성 전이

leehyunjon·2022년 7월 19일
0

JPA

목록 보기
9/10

영속성 전이

영속성 전이란, 특정 엔티티의 영속 상태를 변경할때 연관관계인 엔티티의 영속 상태도 동일한 상태로 변경시켜주는 것을 말한다.

JPA에서는 부모 엔티티를 영속상태로 변경하면 자식 엔티티도 영속상태로 변경해주는 기술을 제공하는데 이를 영속성 전이(CASCADE)라고 한다.

종류

  • CascadeType.ALL : 모두 적용

  • CascadeType.PERSIST : 영속

  • CascadeType.MERGE : 병합
    -영속성 컨텍스트에 저장되어 있는 엔티티를 수정했을 때 persist가 아닌 merge발생

  • CascadeType.REMOVE : 삭제

  • CascadeType.REFRESH : REFRESH

  • CascadeType.DETACH : DETACH

이 중 가장 많이 사용되는 Persist와 Remove를 알아보자.


저장(Persist)

Persist는 엔티티를 영속상태로 변경해주는 것을 말한다.

즉, CascadeType.PERSIST 설정 시 부모 엔티티가 영속상태가 되면 자식 엔티티도 영속상태가 된다.

public class Member{
	@Id
    private Long id;
    
    String name;
    
    @ManyToOne
    Team team;
}

public class Team{
	@Id
    private Long id;
    
    String name;
    
    @OneToMany(cascade = CascadeType.PERSIST)
    List<Member> members = new ArrayList<>();
}

위와 같은 두개의 엔티티가 있을 때,

Team team = new Team("팀");

Member member1 = new Member("회원1");
member1.setTeam(team);

Member member2 = new Member("회원2");
member2.setTeam(team);

em.persist(team);

부모 엔티티인 team만 영속 상태로 변경하게 되면 자식 엔티티인 member1과 member2는 영속 상태로 변경하는 코드를 작성하지 않았지만 영속상태로 되어 저장되어있다.

주의할 점

영속성 전이는 엔티티와 연관관계 엔티티의 영속화에 대해 편의를 주는 기능을 제공하는 것이지 연관관계 매핑과는 관련없다.

Team team = new Team("팀");

Member member1 = new Member("회원1");
Member member2 = new Member("회원2");

em.persist(team);

위의 코드로 주인인 Member에 연관관계 설정을 해주지 않는다면 team, member1, member2는 저장되지만 member1과 member2는 연관관계 매핑이 되지 않은 상태로 연관관계가 null인 상태로 저장된다.

삭제(Remove)

부모 엔티티를 삭제할 때 자식 엔티티도 함께 삭제된다.

//데이터베이스에 team과 연관관계로 맺어진 member1, member2가 저장되어있다.
Team team = em.find(Team.class, 1);

em.remove(team);

위의 코드를 실행하게 되면 부모 엔티티인 team만 삭제했을 뿐인데 자식 엔티티인 member1과 member2가 함께 삭제된다.

영속 상태에서 부모 엔티티와 자식 엔티티를 삭제할 때는, 자식 엔티티를 먼저 삭제하고 부모 엔티티를 삭제해야한다.

영속성 전이를 사용하지 않는다면 em.remove(member1), em.remove(member2), em.remove(team) 총 3개의 remove를 순차적으로 실행해줘야 한다.


고아 객체

JPA는 부모 엔티티와의 연관관계가 끊어진 자식 엔티티를 자동 삭제해주는 기능을 제공한다.

이를 고아 객체 제거라고 한다.

고아 객체(Orphan)

고아 객체란 부모 엔티티와의 연관관계가 끊어진 자식 엔티티를 말하는 것으로 써 부모 엔티티에서 자식 엔티티에 대한 참조 삭제만 해도 해당 자식 엔티티가 삭제된다.

한 곳에서 참조하는 @OneToMany, @OneToOne에서 만 사용할 수 있다.

public class Member{
	@Id
    private Long id;
    
    private String name;
    
    @ManyToOne
    Team team;
}

public class Team{
	@Id
    private Long id
    
    private String name;
    
    @OneToMany(orphanRemoval = true) //고아 객체 삭제 옵션
    private List<Member> members = new ArrayList<>();
}

위와 같은 연관관계를 가질 때

Team team = em.find(Team.class, 1);

team.remove(0); //team의 자식 엔티티 중 0번째 자식 엔티티가 삭제된다.

삭제할 자식 엔티티를 찾아서 삭제해주는 것이 아니라 부모 엔티티의 자식 엔티티 리스트에서 참조 삭제만 했을 뿐인데 참조 삭제한 자식 엔티티가 삭제된다.

CascadeType.REMOVE와 orpahnRemoval = true의 차이

Remove는 부모 엔티티가 삭제되었을 때 자식 엔티티가 삭제되지 않는다.
부모 엔티티에서 참조 삭제를 하여도 자식 엔티티에는 영향을 받지 않는다.

Orphan은 부모 엔티티가 삭제되었을 뿐만 아니라 부모 엔티티에서 자식 엔티티를 참조 삭제하여도 자식 엔티티가 삭제된다.


Reference

https://ocwokocw.tistory.com/145

https://parkhyeokjin.github.io/jpa/2019/11/06/JPA-chap8.html

https://velog.io/@devsh/JPA-CASCADE-%EC%98%81%EC%86%8D%EC%84%B1-%EC%A0%84%EC%9D%B4

S

profile
내 꿈은 좋은 개발자

0개의 댓글