JPA

  • 영속성 전이 : cascade
  • 고아객체 : orphanRemoval

01. 영속성 전이: CASCADE

  • 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 시을 때,
  • 부모 엔티티를 저장할때, 자식 엔티티도 함께 저장
  • 종류 (ALL, PERSIST 를 많이 쓴다.)
    • ALL : 모두 적용
    • PERSIST : 영속
    • REMOVE : 삭제
    • MERGE : 병합
    • REFRESH : refresh
    • DETACH : detach

1) CASCADE - ALL

  • Entity
@Entity
public class Parent {
  
  @Id
  @GeneratedValue
  private Long id;
  
  private String name;
  
  // ALL 로 선언하면 Parent 를 저장할때 Child 에도 persist 를 날려주겠다는 의미이다.
  @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
  private List<Child> childList = new ArrayList<>();
  
  public void addChild(Child child) {
    childList.add(child);
    child.setParent(this);
  }
}
  • Logic
Child child1 = new Child();
Child child2 = new Child();

Parent parent = new Parent();
parent.addChild(child1);
parent.addChild(child2);

em.persist(parent);  // CASCADE ALL 이면 parent 를 저장할때, Child1, 2 도 함께 저장 된다.
  • 사용 전제
    • Parent 와 Child 의 라이프사이클이 유사할 때,
    • 단일 소유자 - 소유자가 1명일때, Parent 엔티티만 Child를 소유할 때,

02. 고아 객체 : orphanRemoval

  • 고아 객체 제거 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제

  • orphanRemoval = true

  • code

    @Entity
    public class Parent {
        
      @Id
      @GeneratedValue
      private Long id;
        
      private String name;
        
      // orphanRemoval = true, 부모 자식 객체 연관관계가 끊기면 자식객체를 삭제시킨다.
      @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
      private List<Child> childList = new ArrayList<>();
        
      public void addChild(Child child) {
        childList.add(child);
        child.setParent(this);
      }
    }
      
    Parent parent1 = em.find(Parent.class, id);
    parent1.getChildren().remove(0);  // 자식엔티티 컬렉션에서 제거 DELETE FROM child WHERE id = ? 쿼리 발생
    

🚀 주의사항

  • 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
  • 참조하는 곳이 하나일 때 사용해야함!
  • 특정 엔티티가 개인 소유할 때 사용
  • @OneToOne, @OneToMany 만 가능
  • 참고
    • 개념적으로 부모를 제거하면 자식은 고아가 된다. 따라서 고아 객체 제거 기능을 활성화 하면, 부모를 제거할 때 자식도 함께 제거된다. 이것은 CascadeType.REMOVE 처럼 동작한다.
      • @OneToMany(mappedBy = "parent", orphanRemoval = true) 이면 부모삭제시 자식들도 모두 삭제됨
      • @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) 이어도 부모삭제시 자식들도 모두 삭제됨
    • Django의 on_delete=models.CASCADE 와 비슷한것 같다.

Django

class Parent(models.Model):
	name = models.CharField(max_length=255)

class Child(models.Model):
	parent = models.ForeignKeyField(Parent, on_delete=models.CASCADE)

Spring

@Entity
@Table(name = "parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

  	// 부모객체가 삭제되어 자식객체가 고아객체가 되면 삭제
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Child> children;

    // getters and setters
}

@Entity
@Table(name = "child")
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;

    // getters and setters
}



영속성 전이 + 고아 객체, 생명주기

  • CascadeType.ALL + orphanRemoval = true
  • 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거
  • 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있음
  • 도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용

댓글남기기