Eclipselink以多对一关系执行意外插入

时间:2011-06-03 12:51:58

标签: jpa eclipselink many-to-one

我在两个对象之间有一个非常基本的关系:

@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中)表现为例外。
在同一个项目中,我已经建立了一些更复杂的关系,我很惊讶地看到这里的关系不起作用 在此先感谢您的帮助。

2 个答案:

答案 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);

<强>结论:

  1. Eclipselink仅将实施N5视为“预期”。
  2. Hibernate将所有五个实现处理为“预期”。
  3. 没有任何行为符合jpa规范的行为