|  CascadeType

     
ALL - 상위 엔터티에서 하위 엔터티로 모든 작업을 전파 모두 전파
PERSIST - 상위 엔터티에서 저장을 하면 하위 엔터티도 저장 (영속성 전파) x.persist() 전파
MERGE - 하위 엔터티까지 병합 작업을 지속 ...(?) x.merge() 전파
REMOVE - 하위 엔터티까지 제거 작업을 지속 x.remove() 전파
REFRESH - 하위 엔터티까지 인스턴스 값 새로 고침 (다시 조회) x.refresh() 전파
DETACH - 하위 엔터티까지 엔터티 제거 x.detach() 전파

* persist() 는 리턴값이 없는 insert, merge() 는 리턴값이 없는 update

@Transactional
    public <S extends T> S save(S entity) {
        if (this.entityInformation.isNew(entity)) {
            this.em.persist(entity);
            return entity;
        } else {
            return this.em.merge(entity);
        }
    }

* save() 는 리턴값이 있는 insert, update이다.

 

|  예시 코드

- Product (상품) 하위에 옵션으로 들어가는 Item들이 있다고 할 때,

- Product의 List<ProductItem> productItems에 @OneToMany(cascade = CascadeType.ALL)을 달아주어, 상품에 대한 CRUD가 이루어질 때 하위 엔터티인 productItems의 ProductItem까지 영향을 받는다. 

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@AuditOverride(forClass = BaseEntity.class)
@Audited  // Entity가 변할 때마다, 변화된 내용을 저장
public class Product extends BaseEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Long sellerId;

    private String name;
    private String description;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "product_id")
    private List<ProductItem> productItems = new ArrayList();


    public static Product of(Long sellerId, AddProductForm form) {
        return Product.builder()
                .sellerId(sellerId)
                .name(form.getName())
                .description(form.getDescription())
                .productItems(form.getAddProductItemForms().stream()
                        .map(p -> ProductItem.of(sellerId, p)).collect(Collectors.toList())
                ).build();
    }
}
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@AuditOverride(forClass = BaseEntity.class)
@Audited
public class ProductItem extends BaseEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long sellerId;

    @Audited
    private String name;

    @Audited
    private Integer price;

    private Integer count;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "product_id")
    private Product product;

    public static ProductItem of(Long sellerId, AddProductItemForm form) {
        return ProductItem.builder()
                .sellerId(sellerId)
                .name(form.getName())
                .price(form.getPrice())
                .count(form.getCount())
                .build();
    }
}

>> 이슈! : 하위에서 삭제시, 상위로 CasecadeType.ALL이 전파되었다. (전부 다 삭제됨)

>>> 수업에서 해결할 때에는, 하위의 CascadeType.ALL을 지웠더니 해결되었다.

 

[ 출처 및 참조 ]

부트캠프 수업 내용 정리

https://data-make.tistory.com/668

 

[JPA] Spring JPA CascadeType 종류

JPA Cascade Types Spring JPA CascadeType 종류 javax.persistence.CascadeType JPA Cascade Type ALL PERSIST MERGE REMOVE REFRESH DETACH CascadeType.ALL 상위 엔터티에서 하위 엔터티로 모든 작업을 전파 @Entity public class Person { @Id @Gen

data-make.tistory.com

https://gimmesome.tistory.com/207

 

[JPA] save와 persist차이 (save, persist, merge개념)

persist()는 리턴값이 없는 insert다. merge()는 리턴값이 없는 update다. save()는 리턴값이 있는 insert, update다. save 메소드를 호출하면.... entityInformation에서 새로운 entity이면 persist()를 그게 아니면 merge()

gimmesome.tistory.com

https://umanking.github.io/2019/04/12/jpa-persist-merge/

+ Recent posts