我在两个对象之间有一个非常基本的关系:
@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中)的行为也不例外
在同一个项目中,我已经建立了一些更复杂的关系,看到这里的关系不起作用,我真的很惊讶
提前感谢您的帮助。
statusOfADao.getStatusOfAById()做什么?
它是否使用相同的持久性上下文(相同的事务和EntityManager)?
您需要使用相同的EntityManager,因为不应该混合来自不同持久性上下文的对象。
saveOrPersistA到底做什么?merge()调用应该能正确地解析所有内容,但如果您确实把对象搞砸了,那么可能很难按照预期合并所有内容。
你只是合并了A,还是合并了它的状态?也可以尝试将状态设置为状态的合并结果。
假设:@Id@GeneratedValue(策略=GenerationType.IDENTITY)
让我们考虑statusOfADao.getStatusOfAById(456)的以下实现:
1.返回只有id集的"代理"对象:
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()commit();return 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);
结论:
- Eclipselink只按"预期"处理实现N5
- Hibernate按照"预期"处理所有五个实现
- 没有分析什么行为符合jpa规范