man*_*ish 2 hibernate hibernate-cascade spring-data-jpa jpa-2.1
考虑以下 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); }
}
}
Run Code Online (Sandbox Code Playgroud)
注意从CartItem到的关联Stock。此关联已被注释,以便更改购物车项目数量会影响其在另一个方向上的可用库存,即,如果购物车项目数量增加,则产品的可用库存数量减少,反之亦然。
这使我可以触发cartRepository.save(cart),保存所有购物车项目并同时更新他们的库存(由于Cascade.ALLfrom Cartto CartItem)。只要购物车项目的数量非零,这就可以正常工作。
但是,当cartRepository.save(cart)在调用后调用时cart.removeItem(item),级联也会尝试删除购物车项目的库存,这不是意图。应删除购物车项目,但应简单地更新其关联的库存。有没有一种方法,以级联更新,从CartItem到Stock,但级联删除在CartItem上更新Stock?
改变
class CartItem {
@JoinColumn(name = "stock_id", updatable = false)
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Stock stock;
}
Run Code Online (Sandbox Code Playgroud)
到
class CartItem {
@JoinColumn(name = "stock_id", updatable = false)
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST }, fetch = FetchType.LAZY)
private Stock stock;
}
Run Code Online (Sandbox Code Playgroud)
( CascadeType.ALLto { CascadeType.MERGE, CascadeType.PERSIST }) 解决了这个问题。以前在cartItem.setQuantity(0)调用时执行以下 SQL 查询:
delete from cart_item where id=?
delete from stock where id=?
Run Code Online (Sandbox Code Playgroud)
进行更改后,将根据需要执行以下 SQL 查询:
update stock set quantity=? where id=?
delete from cart_item where id=?
Run Code Online (Sandbox Code Playgroud)
Github上提供了示例应用程序,用于检查解决方案的正确性。
| 归档时间: |
|
| 查看次数: |
8145 次 |
| 最近记录: |