gpt4 book ai didi

java - Spring Data JPA - 如何保留任何现有的嵌套对象

转载 作者:行者123 更新时间:2023-12-04 08:27:13 26 4
gpt4 key购买 nike

使用 Springboot 2.4.0,我正在尝试开发一个简单的模块来管理实体之间的典型关系 ProductOrder (多对多关系)。
按顺序,我有这个 products field :

@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 的 CRUD实体启动并正常运行,因此我可以通过产品存储库插入产品:
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 更改为 CascadeType.MERGE ,我只能将现有产品链接到新订单,但对于新产品,我收到此错误:

  • org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.gallelloit.productcrud.model.Product; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.gallelloit.productcrud.model.Product


  • 我给 CascadeType 设置的任何其他值(包括 CascadeType.ALL ),我得到相反的结果:新产品被保存并链接到新订单,但对于现有产品,我收到此错误:

  • detached entity passed to persist:com.gallelloit.productcrud.model.Product; nested exception isorg.hibernate.PersistentObjectException: detached entity passed topersist: com.gallelloit.productcrud.model.Product


    我知道我可以“手动”获取每个产品,并将它们保存在 order.save() 之前。 ,但我想知道 Spring Data 是否为您做到了。
    任何的想法?

    最佳答案

    依托CascadeType.MERGE在这种情况下是不安全的,因为它更新了相关的 Product s 也是如此,这意味着您可能会无意中覆盖现有的 Product数据。
    您可以通过要求 JPA 为现有实体创建代理而不是实际从数据库中获取它们的关联状态来优化现有产品的获取。这可以使用 JpaRepository.getOne() 来完成。 .你需要这样的东西:

    order.setProducts(order.getProducts()
    .map(product -> product.getId() == null ? productRepository.save(product) : productRepository.getOne(product.getId())
    .collect(Collectors.toList());
    如果您决定使用 CascadeType.PERSISTCascadeType.ALL ,当然可以替换 productRepository.save(product)只需 product . CascadeType.ALL@ManyToMany 没有意义, 但是,因为它意味着 CascadeType.REMOVE ,你肯定不想要的。
    另外,我假设保存订单的逻辑发生在事务上下文中,对吗?

    关于java - Spring Data JPA - 如何保留任何现有的嵌套对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65203543/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com