Java 使用CascadeType.MERGE与Spring数据存储库的正确方法是什么?
在提交保存Java 使用CascadeType.MERGE与Spring数据存储库的正确方法是什么?,java,spring,jpa,spring-boot,spring-data,Java,Spring,Jpa,Spring Boot,Spring Data,在提交保存entity2和entity3实例的事务时,每个实例都保存对Entity1(Entity1)实例的引用,导致数据库中出现Entity1的两条记录(因为保存每个实例时都会保存引用) 如果我有两个Spring数据存储库-Entity2Repository和Entity3Repository,我执行以下操作将导致数据库中包含实体1的两个实例: Entity1 entity1 = new Entity1(); entity1.name = "Name1"; entity1.value = "V
entity2
和entity3
实例的事务时,每个实例都保存对Entity1(Entity1)实例的引用,导致数据库中出现Entity1的两条记录(因为保存每个实例时都会保存引用)
如果我有两个Spring数据存储库-Entity2Repository
和Entity3Repository
,我执行以下操作将导致数据库中包含实体1的两个实例:
Entity1 entity1 = new Entity1();
entity1.name = "Name1";
entity1.value = "Value1";
Entity2 entity2 = new Entity2();
entity2.name = "Name2";
entity2.value = "Value2";
entity2.setEntity1(entity1);
Entity3 entity3 = new Entity3();
entity3.name = "Name3";
entity3.value = "Value3";
entity3.setEntity1(entity1);
Entity2Repository.save(entity2);
Entity3Repository.save(entity3);
简短回答
它将正常工作(只生成一条entity1
记录)
长话短说
示例代码执行的实际结果取决于测试方法上是否存在注释
Entity2Repository.save(entity2);
Entity3Repository.save(entity3);
这些调用将调用方法,该方法本身就是@Transactional
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
没有@Transactional
将有两个事务-每个save()
调用一个事务
,entity1
和entity2
现在是瞬态的entity3
- 调用了Entity2Repository.save(entity2)
- 事务被打开,会话被创建
作为新实体为persist()
调用entity2
被级联到persist()
entity1
和entity1
是持久的现在,它们连接到 本届会议entity2
- 事务已提交,会话已关闭
和entity1
现在已分离entity2
- 调用了Entity3Repository.save(entity3)
- 事务被打开,会话被创建
作为新实体为persist()
调用entity3
被级联到persist()
entity1
org.springframework.dao.InvalidDataAccessApiUsageException:抛出传递给persist的分离实体
- 事务回滚,会话关闭
entity1
和entity2
条目保存在数据库中
带有@Transactional
默认情况下@Transactional传播是-只有一个事务
,entity1
和entity2
现在是瞬态的entity3
- 事务被打开,会话被创建
- 调用了Entity2Repository.save(entity2)
作为新实体为persist()
调用entity2
被级联到persist()
entity1
和entity1
是持久的现在,它们已附加到当前会话entity2
- 调用了Entity3Repository.save(entity3)
作为新实体为persist()
调用entity3
级联到一级缓存中找到的托管实体persist()
entity1
是持久的现在,它已附加到当前会话entity3
- 事务已提交,会话已关闭
entity1
、entity2
和entity3
条目保存在数据库中
public boolean isNew() {
return null == getId();
}