These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Semantics of EntityManager.contains() method
PostPosted: Wed Aug 05, 2009 7:40 am 
Newbie

Joined: Wed Aug 05, 2009 7:00 am
Posts: 1
Hi all,

I'm having a problem with hibernate's implementation of the EntityManager interface - specifically the contains() method, and I'd appreciate any help you can offer.

My application works with a complex graph of objects, and implements the session per request pattern, using detached objects while the graph is constructed and merging when it comes to persist. This application works exclusively with the JPA interfaces, hiding the hibernate implementation.

My problem is specifically related to the graph of objects and cascading merges. The following example is a drastic oversimplification (and please excuse the pseudocode!) but illustrates my problem:

Code:
@MappedSuperClass
public abstract Class Person {
  // acc is a business key for every person instance
  @Column
  private String acc;

  ...
}

@Entity
public class Parent extends Person {
  @OneToMany{
    cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    ...}
  private Child child;

  public void setChild(Child child) {...}

  public Child getChild() {...}
}

@Entity
public class Child extends Person {
 
  ...
}


Assume that my application contains references to a set of parent instances and a set of child instances. Some of the child instances are references by a parent object, some aren't. My application needs to persist all of them. Effectively, my application is doing the following (but obviously with a much more complex graph of objects, and person and child objects will be constructed in separate classes in a multithreaded manner)...

Code:
  Person parent = new Parent();
  Person child = new Child();
  parent.setChild(child);

  // then sometime later...
  entityManager.merge(parent);
  entityManager.merge(child);

  // then, finally...
  transaction.commit();


This fails: because parent cascades the merge to child, my child instance is then stale and when I try to commit I get a ConstraintViolationException (because I'm trying to store two child entires with the same acc). Ideally, I'd simply update my applications references to child after merging but I can't do this for objects that are merged due to a cascade from parent. Further, I don't know in advance whether a reference to child has been set on parent: due to the nature of my set of objects to persist, some may be reached transitively, others not.

I'd hoped that I can simply iterate over a list of instances stored in my app, with the following code...

Code:
for (Person person : getAll()) {
  if (!entityManager.contains(person)) {
    entityManager.merge(person);
  }
}


But, this doesn't work: contains(person) is always false. Even though I have overridden equals() and hashcode() methods as appropriate, I don't get the result I'd expect if contains() followed normal hashset semantics. So I can write code lilke this...

Code:
  Person mergedPerson = entityManager.merge(person);
  log.info("Original person equals merged person? " + person.equals(mergedPerson)); // this is true
  log.info("EntityManager contains original person? " + entityManager.contains(person)); // this is false
  log.info("EntityManager contains merged person? " + entityManager.contains(mergedPerson)); // this is true


In this case, because person and mergedPerson are equal, I would have expected the second call to return true, not false. Given that my graph of objects is complex and it is not easy to keep track of, and update, all the references between all objects, is there some other way I can check whether a person has already been merged?

Thanks in advance,

Tony.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.