使用springboot2.4.0,我试图开发一个简单的模块来管理实体之间的典型关系 Product
以及 Order
(许多关系)。
按顺序,我有这个 products
字段:
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
name="products_orders",
joinColumns=@JoinColumn(name="order_id"),
inverseJoinColumns=@JoinColumn(name="product_id")
)
private List<Product> products;
因为我不需要它,现在我省略了一个 orders
中的字段 Product
实体。
在这段感情之前,我有一个坏习惯 Product
实体已启动并正常运行,因此我可以通过产品存储库插入产品:
public interface ProductRepository extends JpaRepository<Product, Integer>
我需要订购一批产品。我有这个密码:
List<Products> myListOfProducts = new ArrayList<>();
myListOfProducts.add(previouslyExistingProduct);
myListOfProducts.add(nonExistingProduct);
Order myorder = new Order(myListOfProducts, "mail", LocalDateTime.now());
myorder.save();
问题是:是否可以使用以前的代码保存新订单以及与其链接的产品(同时保存现有和不存在的产品)?
这是订单存储库:
public interface OrderRepository extends JpaRepository<Order, Integer>
到目前为止我得到的是:
如果我把类型改成 CascadeType.MERGE
,我只能将现有产品链接到新订单,但对于新产品,我得到以下错误:
org.hibernate.transientobjectexception:对象引用未保存的 transient 示例-刷新前保存 transient 示例:com.gallelloit.productcrud.model.product;嵌套异常为java.lang.illegalstateexception:org.hibernate.transientObject异常:对象引用未保存的临时示例-刷新前保存临时示例:com.gallelloit.productcrud.model.product
我输入到cascadetype的任何其他值(包括 CascadeType.ALL
),我得到相反的结果:新产品已保存并链接到新订单,但对于现有产品,我得到以下错误:
传递给persist的分离实体:com.gallelloit.productcrud.model.product;嵌套异常为org.hibernate.persistentobjectexception:传递给persist的分离实体:com.gallelloit.productcrud.model.product
我知道我可以“手动”获取每一个产品,并在发布之前保存它们 order.save()
,但我想知道spring数据是否为您做到了这一点。
你知道吗?
1条答案
按热度按时间yws3nbqq1#
依靠
CascadeType.MERGE
在此上下文中不安全,因为它更新关联的Product
s,这意味着您可能会无意中覆盖现有的Product
数据。您可以通过请求jpa为现有实体创建代理来优化现有产品的获取,而不是从db实际获取它们的关联状态。这可以使用
JpaRepository.getOne()
. 你需要一些东西,比如:如果你决定使用
CascadeType.PERSIST
或者CascadeType.ALL
,当然可以替换productRepository.save(product)
只是product
.CascadeType.ALL
对我来说没有意义@ManyToMany
不过,因为这意味着CascadeType.REMOVE
你肯定不想要。另外,我假设保存订单的逻辑发生在事务上下文中,对吗?