2011-09-21 83 views
4

我有2个JPA实体之间有一个双向关系。合并JPA实体返回旧值

@Entity 
public class A { 

    @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    B b; 

    // ... 
} 

@Entity 
public class B { 

    @OneToMany(mappedBy="b",cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    Set<A> as = new HashSet<A>(); 

    // ... 
} 

现在我更新分离A其中也有一些Bs反之亦然关系的一些字段值,并通过

public String save(A a) { 
    A returnedA = em.merge(a); 
} 

returnedA现在已经把它合并A在更新之前的值。 我想,

FINEST: Merge clone with references [email protected] 
    FINEST: Register the existing object [email protected] 
    FINEST: Register the existing object [email protected] 
    FINEST: Register the existing object [email protected] 

表明,在B中的引用As(其中仍然有旧值)负责覆盖新的?

有没有人有提示如何防止这种情况发生?

任何想法,非常感谢!

在此先感谢。

+1

一个快速的想法:从Bs中删除合并级联。 – Thomas

+0

感谢您的建议,@Thomas。这肯定会有所帮助,但不幸的是,由于经常发生双向更新,我宁愿保留它。 – Dirk

+1

不是一个理想的解决方案,但假设你拥有一个包含.save(A a)和.save(B B)的方法,你可以随时删除级联和手动处理级联.. – rhinds

回答

1

Dirk,我有一个类似的问题和解决方案(我可能不会正确利用API)是密集型的。 Eclipselink维护一个对象缓存,如果它们没有更新(合并/持久化),数据库通常会反映更改,但级联对象不会更新(特别是父节点)。

(我声明了一个作为记录连接多个B的) 实体:

public class A 
{ 
    @OneToMany(cascade = CascadeType.ALL) 
    Collection b; 
} 

public class B 
{ 
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}) //I don't want to cascade a persist operation as that might make another A object) 
    A a; 
} 

在上述解决办法的情况下:

public void saveB(B b) //"Child relationship" 
{ 
    A a = b.getA();//do null checks as needed and get a reference to the parent 
    a.getBs().add(b); //I've had the collection be null 
    //Persistence here 
    entityInstance.merge(a); // or persist this will cascade and use b 
} 

public void saveA(A a) 
{ 
    //Persistence 
    entityInstance.merge(a) // or persist 
} 

你在做什么这里是物理从顶部级联合并链。维护令人烦恼,但它确实解决了问题。或者,你可以通过检查它是否被分离并刷新/替换来处理它,但是我发现它不太理想,并且不适合使用。

如果有人对什么是正确的设置有更好的答案,我会很乐意听到它。现在我已经为我的关系实体采用了这种方法,并且它维护起来令人恼火。

祝您好运,我很乐意听到更好的解决方案。

+0

感谢单一的中央服务/ DAO类你的回答,这对我来说似乎是一个可行的解决方案。 – Dirk