| 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
'Framework > Orm&Mapper' 카테고리의 다른 글
[JPA] 특정 상황에서 Lazy Fetch Type 변경하기 (@EntityGraph) (0) | 2022.11.28 |
---|---|
[JPA] Lazy Loading 개념 (0) | 2022.11.11 |
[Entity] 중복데이터 저장 방지 (Unique Key, Index) (0) | 2022.11.11 |
[Transaction] Transaction에 대한 이해 (& 스프링의 @Transactionl) (1) | 2022.10.25 |
[JPA] 인텔리J에서 JPA Entity 기반 ERD 그리기 (0) | 2022.10.19 |