Java SpringDataJPA-如何持久化嵌套对象(无论是否存在)
使用Springboot 2.4.0,我试图开发一个简单的模块来管理实体Java SpringDataJPA-如何持久化嵌套对象(无论是否存在),java,spring-boot,orm,spring-data-jpa,spring-data,Java,Spring Boot,Orm,Spring Data Jpa,Spring Data,使用Springboot 2.4.0,我试图开发一个简单的模块来管理实体产品和订单(多个关系)之间的典型关系 按顺序,我有以下产品字段: @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinTable( name="products_orders", joinColumns=@JoinColumn(name="order_id"),
产品
和订单
(多个关系)之间的典型关系
按顺序,我有以下产品
字段:
@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;
我需要下一个订单,里面有很多产品。我有以下代码:
List<Products> myListOfProducts = new ArrayList<>();
myListOfProducts.add(previouslyExistingProduct);
myListOfProducts.add(nonExistingProduct);
Order myorder = new Order(myListOfProducts, "mail", LocalDateTime.now());
myorder.save();
List myListOfProducts=new ArrayList();
添加(以前存在的产品);
添加(不存在的产品);
Order myorder=新订单(myListOfProducts,“mail”,LocalDateTime.now());
myorder.save();
问题是:是否可以使用以前的代码保存新订单以及与其链接的产品(保存现有和不存在的产品)
这是订单存储库:
public interface ProductRepository extends JpaRepository<Product, Integer>
public interface OrderRepository extends JpaRepository<Order, Integer>
公共接口OrderRepository扩展了JpaRepository
到目前为止,我得到的是:
- 如果我将CascadeType更改为
,我只会将现有产品链接到新订单,但对于新产品,我会出现以下错误:CascadeType.MERGE
- 我对CascadeType(包括
)输入的任何其他值都会得到相反的结果:新产品会被保存并链接到新订单,但对于现有产品,我会得到以下错误:CascadeType.ALL
有什么想法吗?依赖于
CascadeType.MERGE
在这种情况下是不安全的,因为它也会更新相关的产品
s,这意味着您可能会无意中覆盖现有的产品
数据
您可以通过要求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
对于@manytomy
来说没有意义,因为它意味着CascadeType.REMOVE
,这是您最不想要的
另外,我假设保存订单的逻辑发生在事务上下文中,对吗?谢谢您的回答。该代码将放在哪里?我猜是在订单服务中,对吧?这是一个很好的解决办法。只有两个疑问。一个不太重要的问题是:它使我将productRepository注入OrderServiceImpl类中。这没什么大不了的。。。但到目前为止我还没有做过,现在我不得不这么做。正如我所说,没什么大不了的。另一个是:什么产品不存在,getOne方法返回null?我会在列表中插入空值吗?会有什么样的行为?我必须“手动”处理这种可能性吗?这个问题中的一个错误:“另一个是:任何产品不存在,getOne方法返回null?”它应该说:“另一个是:如果任何产品不存在,getOne方法返回null怎么办?”
getOne
从不返回null
。JPA在使用getOne
时不检查实体的存在性,这就是关键所在-以避免额外的查询。如果id没有指向PRODUCT
表中的有效行,那么您将从DB获得完整性约束冲突,thoughPerfect。我最终在order.setProducts中执行了一些验证,方法与您所解释的类似。最后一个问题:JPA创建的代理是否响应代理设计模式?或者JPA创建了什么样的代理?你能为我参考一些文章来了解一下它们吗?谢谢!!最好的参考可能是。是的,它遵循代理模式,也就是说,如果你试图访问它的数据,它将被加载并返回,因此代理对于你的应用程序来说是透明的