在this question提交保存entity2
和entity3
实例的事务,每个实例都持有对Entity1(entity1)实例的引用,导致出现的entity1的两条记录数据库(因为保存每个实例时保存引用)。
如果我有2个Spring数据存储库 - Entity2Repository
和Entity3Repository
,我将执行以下操作,这将导致数据库中包含2个实体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);
答案 0 :(得分:5)
它将正常工作(只生成entity1
的一条记录。
示例代码执行的实际结果取决于测试方法中@Transactional注释的存在。
Entity2Repository.save(entity2);
Entity3Repository.save(entity3);
这些调用将调用SimpleJpaRepository#save()方法,即@Transactional本身。
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
另外,如您所见,您不应该担心持久/合并调用 - 如果它是新实体,则会调用persist()
。 isNew()
检查非常简单(请参阅AbstractPersistable源代码):
public boolean isNew() {
return null == getId();
}
没有@Transactional
将有两个交易 - 每个save()
来电一个。
entity1
,entity2
和entity3
TRANSIENT 现在Entity2Repository.save(entity2)
已被调用persist()
被调用entity2
,因为它是新实体persist()
级联为entity1
entity1
和entity2
现在 PERSISTENT ,它们附在
本届会议entity1
和entity2
已脱离现在Entity3Repository.save(entity3)
已被调用persist()
被调用entity3
,因为它是新实体persist()
级联为entity1
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist
被抛出 entity1
和entity2
条目保存在数据库中。
使用@Transactional
默认@Transactional传播是REQUIRED
- 只有一个交易。
entity1
,entity2
和entity3
TRANSIENT 现在Entity2Repository.save(entity2)
已被调用persist()
被调用entity2
,因为它是新实体persist()
级联为entity1
entity1
和entity2
现在 PERSISTENT ,它们附加到当前会话Entity3Repository.save(entity3)
已被调用persist()
被调用entity3
,因为它是新实体persist()
级联到entity1
,在第一级缓存中找到的托管实体entity3
现在 PERSISTENT ,它附加到当前会话 entity1
,entity2
和entity3
条目保存在数据库中。