Рассмотрим следующие объекты JPA:Предотвращение удаления от каскадного к экземпляру объекта
@Entity @Table(name = "product") class Product { ... }
@Entity @Table(name = "stock") class Stock {
@JoinColumn(name = "product_id", updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Product product;
@Column(name = "quantity")
private Long quantity;
}
@Entity @Table(name = "cart") class Cart {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "cart", orphanRemoval = true)
private List<CartItem> items = new ArrayList<>();
public void addItem(CartItem item) { items.add(item); }
public void removeItem(CartItem item) { items.remove(item); }
}
@Entity @Table(name = "cart_item") class CartItem {
@JoinColumn(name = "cart_id", updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Cart cart;
@JoinColumn(name = "product_id", updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Product product;
@Column(name = "quantity")
private Long quantity;
@JoinColumn(name = "stock_id", updatable = false)
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Stock stock;
public void setQuantity(Long quantity) {
final Long delta = this.quantity - Math.max(0L, quantity);
this.quantity += delta;
this.stock.setQuantity(this.stock.getQuantity() - delta);
if(quantity < 1) { cart.removeItem(this); }
}
}
Обратите внимание на ассоциацию с CartItem
к Stock
. Эта ассоциация была аннотирована таким образом, что изменение количества предметов корзины влияет на ее доступный запас в другом направлении, то есть, если количество предметов корзины увеличивается, доступное количество запаса для продукта уменьшается и наоборот.
Это позволяет мне стрелять cartRepository.save(cart)
, сохраняя все элементы корзины и обновления их запасов в то же время (в связи с Cascade.ALL
от Cart
к CartItem
). Это отлично работает, если элемент корзины имеет ненулевое количество.
Однако, когда cartRepository.save(cart)
вызывается после вызова cart.removeItem(item)
, каскад также пытается удалить запас для позиции корзины, что не является целью. Элемент корзины должен быть удален, но связанный с ним запас должен быть просто обновлен. Есть ли способ каскадного обновления от CartItem
до Stock
, но каскад удаляет по CartItem
как обновления на Stock
?