Merging JPA entity returns old values
I have 2 JPA entities that have a bidirectional relationship between them.
@Entity
public class A {
@ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE})
B b;
// ...
}
and
@Entity
public class B {
@OneToMany(mappedBy="b",cascade={CascadeType.PERSIST, CascadeType.MERGE})
开发者_运维知识库 Set<A> as = new HashSet<A>();
// ...
}
Now I update some field values of a detached A
which also has relationships to some Bs
and vice versa and merge it back by
public String save(A a) {
A returnedA = em.merge(a);
}
returnedA
now has the values of A prior to updating them.
I suppose that
FINEST: Merge clone with references A@a7caa3be
FINEST: Register the existing object B@cacf2dfb
FINEST: Register the existing object A@a7caa3be
FINEST: Register the existing object A@3f2584b8
indicates that the referenced As
in B (which still have the old values) are responsible for overwriting the new ones?
Does anyone have a hint how to prevent this to happen?
Any idea is greatly appreciated!
Thanks in advance.
Dirk, I've had a similar problem and the solution (I might not be leveraging the API correctly) was intensive. Eclipselink maintains a cache of objects and if they are not updated (merged/persisted) often the database reflects the change but the cascading objects are not updated (particularly the parents).
(I've declared A as the record joining multiple B's) Entities:
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;
}
In the case above a workaround is:
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
}
What you're doing here is physically cascading the merge down the chain from the top. It is irritating to maintain, but it does solve the problem. Alternatively you can deal with it by checking if it is detached and refreshing/replacing but I've found that to be less desirable and irritating to work with.
If someone has a better answer as to what the correct setup is I would be happy to hear it. Right now I've taken this approach for my relational entities and it is definitely irritating to maintain.
Best of luck with it, I'd love to hear a better solution.
精彩评论