我在两个对象之间有一个非常基本的关系:
@Entity
public class A {
@ManyToOne(optional = false)
@JoinColumn(name="B_ID", insertable=false, updatable=true)
private StatusOfA sa;
getter+setter
}
@Entity
public class StatusOfA {
@Id
private long id;
@Column
private String status;
getter+setter
}
DB中只有一组有限的StatusOfA 我在事务中对A执行更新:
@TransactionalAttribute
public void updateStatusOfA(long id) {
A a = aDao.getAById(123);
if(a != null) {
a.getStatusOfA().getId(); //just to ensure that the object is loaded from DB
StatusOfA anotherStatusOfA = statusOfADao.getStatusOfAById(456);
a.setStatusOfA(aontherStatusOfA);
aDao.saveOrPersistA(a);
}
}
saveOrPersistA方法在这里合并'a'。
我希望Eclipselink只对'a'执行更新以更新StatusOfA,但它正在StatusOfA表上执行新的插入。然后Oracle因为一个独特的约束违规而抱怨(Eclipselink试图保留的StatusOfA已经存在......)。
这里没有级联,所以问题不存在,Hibernate(在JPA2中)表现为例外。
在同一个项目中,我已经建立了一些更复杂的关系,我很惊讶地看到这里的关系不起作用
在此先感谢您的帮助。
答案 0 :(得分:0)
statusOfADao.getStatusOfAById()做了什么?
它是否使用相同的持久化上下文(相同的事务和EntityManager)?
您需要使用相同的EntityManager,因为您不应混合来自不同持久性上下文的对象。
saveOrPersistA究竟做了什么? merge()调用应该正确解决所有问题,但如果你真的弄乱了对象,可能很难按预期合并所有内容。
你是在合并A还是它的状态?尝试将状态设置为状态的合并结果。
答案 1 :(得分:0)
假设: @ Id @ GeneratedValue(strategy = GenerationType.IDENTITY)
让我们考虑一下statusOfADao.getStatusOfAById(456)的以下实现:
<强> 1。返回只有id设置的“proxy”对象:
return new StatusOfA(456);
<强> 2。在新交易中返回实体:
EntityManager em = emf.createEntityManager();em.getTransaction().begin();
StatusOfA o = em.find(StatusOfA.class,456); // em.getReference(StatusOfA.class,456); em.getTransaction()提交(); 返回o;
<强> 3。返回分离的实体:
StatusOfA o = em.find(StatusOfA.class,456);//em.getReference(StatusOfA.class,456);
em.detached(o);
return o;
<强> 4。返回反序列化序列化实体:
return ObjectCloner.deepCopy(em.find(StatusOfA.class,456));
<强> 5。返回附加实体:
return em.find(StatusOfA.class,456);
<强>结论:强>