spring-data-jpa-如何持久化任何现有或不存在的嵌套对象

9vw9lbht  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(343)

使用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数据是否为您做到了这一点。
你知道吗?

yws3nbqq

yws3nbqq1#

依靠 CascadeType.MERGE 在此上下文中不安全,因为它更新关联的 Product s,这意味着您可能会无意中覆盖现有的 Product 数据。
您可以通过请求jpa为现有实体创建代理来优化现有产品的获取,而不是从db实际获取它们的关联状态。这可以使用 JpaRepository.getOne() . 你需要一些东西,比如:

order.setProducts(order.getProducts()
    .map(product -> product.getId() == null ? productRepository.save(product) : productRepository.getOne(product.getId())
    .collect(Collectors.toList());

如果你决定使用 CascadeType.PERSIST 或者 CascadeType.ALL ,当然可以替换 productRepository.save(product) 只是 product . CascadeType.ALL 对我来说没有意义 @ManyToMany 不过,因为这意味着 CascadeType.REMOVE 你肯定不想要。
另外,我假设保存订单的逻辑发生在事务上下文中,对吗?

相关问题