开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜