[실험] 프록시와 CASCADE 를 더 잘 이해하기 위한 테스트
CASCADE 실험들
cascade: 연관된 객체끼리 연속적으로 persist 적용가능
team - member - locker 세 객체는 각각 1:N, 1:1 관계의 객체들이다
이 객체들은 모두 서로 연관관계 매핑이 되어있다
이때 CascadeType.PERSIST
로 설정하고
team 객체만을 저장하면 연관된 객체가 모두 저장된다
cascade: 부모가 아닌 자식으로 저장해도 persist 가능
parentA.addChildren(childA, childB);
em.persist(childB);
cascade: 여러 깊이에 걸쳐서 적용이 되는가?
예를들어 grand parent > parent > child 대로 persiste 가 적용되는지를 실험해보았다
결론: 가능하다 !
비즈니스 로직
GrandParent grandParentA = GrandParent.builder().name("grand parent A").build();
Parent parentA = Parent.builder().name("parent A").build();
Parent parentB = Parent.builder().name("parent B").build();
Child childA = Child.builder().name("child A").build();
Child childB = Child.builder().name("child B").build();
Child childC = Child.builder().name("child C").build();
grandParentA.addParents(parentA, parentB);
parentA.addChildren(childA, childB);
parentB.addChildren(childC);
em.persist(grandParentA);
조부모 클라쓰
@Entity(name = "GRAND_PARENT")
@Builder
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class GrandParent {
@Id
@GeneratedValue(generator = "uuid_gen")
@GenericGenerator(name = "uuid_gen", strategy = "uuid")
private String id;
private String name;
@Builder.Default
@OneToMany(mappedBy = "grandParent", cascade = CascadeType.PERSIST)
private List<Parent> parents = new ArrayList<>();
public void addParents(Parent... parents) {
this.parents.addAll(Arrays.asList(parents));
Arrays.stream(parents).forEach(parent -> parent.mapGrandParent(this));
}
}
부모 클라쓰
@Entity
@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Parent {
@Id @GeneratedValue
private Long id;
private String name;
@Builder.Default
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
private List<Child> children = new ArrayList<>();
@JoinColumn(name = "GRAND_PARENT_ID")
@ManyToOne(fetch = FetchType.LAZY)
private GrandParent grandParent;
public void addChildren(Child... children) {
this.children.addAll(Arrays.asList(children));
Arrays.stream(children).forEach(child -> child.mapParent(this));
}
public void mapGrandParent(GrandParent grandParent){
this.grandParent = grandParent;
}
}
@Entity
@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Child {
@Id @GeneratedValue
private Long id;
private String name;
@JoinColumn(name = "PARENT_ID")
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private Parent parent;
public void mapParent(Parent parent) {
this.parent = parent;
parent.getChildren().add(this);
}
}
Self Join을 하는 연관관계 경우 연쇄적으로 적용가능?
공부하는 개발자 핑구님의 궁금중 중에
Self Join
을 하는 로직이 있어서 재귀적으로 적용한지도 실험해보았다 (delete)
이 경우는 연쇄적으로 적용가능하다 !
Folder
@Entity
@SequenceGenerator(
name = "FOLDER_SEQ_GEN" ,
sequenceName = "FOLDER_SEQ" ,
initialValue = 1
)
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Folder {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE , generator = "FOLDER_SEQ_GEN")
private long id;
private String name;
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Folder parent;
@BatchSize(size = 900)
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Folder> children = new ArrayList<>();
@Override
public String toString() {
return "Folder{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
여러 뎁스에 걸친 orphanRemoval 테스트
조부모 > 부모 > 자식 구조일때
조부모의 특정 부모를 삭제하면 그때의 자식도 제거되는지를 테스트해보았다
grandParentA.getParents().remove(0);
결론
부모, 자식에 걸쳐서 모두 제거 된다
Parent와 Child 가 일대다
Parent와 ChildSecond 일대다
일 경우
부모를 삭제하면 자식도 삭제된다 !
Parent parentA = Parent.builder().name("parent A").build();
Child childA = Child.builder().name("child A").build();
Child childB = Child.builder().name("child B").build();
ChildSecond childSecond = ChildSecond.builder().name("child 2-A").build();
parentA.addChildren(childA);
parentA.addChildren(childB);
parentA.addChildrenSecond(childSecond);
em.persist(parentA);
em.flush();
em.remove(parentA);
기타 알게된 것 UUID 채번전략
https://github.com/LeoHeo/spring-tips/blob/master/jpa-uuid.md
https://github.com/hibernate/hibernate-orm/blob/9b00aaf9a55f9879a512b34c13dd25425264494b/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java#L64
https://kapentaz.github.io/jpa/Hibernate%EC%97%90%EC%84%9C-Custom-ID-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0/#