【发布时间】:2012-01-22 06:52:29
【问题描述】:
我在单个事务中遇到多个EntityManager.merge() 调用的问题。这是使用 Oracle 数据库。两个对象都不存在。实体:
public class A {
@Id
@Column("ID")
public Long getID();
@OneToOne(targetEntity = B.class)
@JoinColumn("ID")
public B getB();
}
public class B {
@Id
@Column("ID")
public Long getID();
}
合并代码如下所示:
@Transactional
public void create(Object A, Object B) {
Object A = entitymanager.merge(A);
B.setId(A.getId());
entitymanager.merge(B);
}
对象 A 的 ID 是通过序列生成的,并在 B 上正确设置。查看日志,在调用 B 上的合并之前调用 A 上的合并。有一个从 A 到 B 的 @OneToOne 映射。但是,在方法结束时,当它实际提交时,它会尝试在 B 上执行 INSERT,然后再对 A 执行 INSERT,这会引发 IntegrityConstraintViolation因为“找不到父键”。
如果我在第二次合并之前添加entitymanager.flush(),它可以正常工作。
@Transactional
public void create(Object A, Object B) {
Object A = entitymanager.merge(A);
entitymanager.flush();
B.setId(A.getId());
entitymanager.merge(B);
}
但是,flush() 是一项不必要的昂贵操作。所有这些都应该发生在同一个事务中(@Transactional 的默认传播是Propagation.REQUIRED)。
知道为什么没有flush() 就不能工作吗?为什么即使 A 上的合并发生在 B 上的合并之前,COMMIT 上的实际 INSERT 却相反?
【问题讨论】:
标签: oracle10g eclipselink entitymanager