-->
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.  [ 4 posts ] 
Author Message
 Post subject: Basic JPA @OneToMany / @ManyToOne mapping trouble
PostPosted: Sat Sep 26, 2009 12:07 pm 
Newbie

Joined: Sat Sep 26, 2009 12:00 pm
Posts: 6
I am using JPA in a J2SE application ("resource-local"), and I'm facing the following problem.

Given the following entities (a Project consists of a list of Employees):

Code:
@Entity
public class Project {

   @Id
   @Column(name="PROJECT_ID", nullable = false)
   private long id;


   @OneToMany(mappedBy="project", cascade = CascadeType.ALL)
   private List<Employee> employees;


   Project() {
   }
   
   public List<Employee> getEmployees() {
      return employess;
   }

}

@Entity
public class Employee {

   @Id
   @Column(name="EMPLOYER_ID", nullable = false)
   private long id;

   @ManyToOne
   @JoinColumn(name="PROJECT_ID")
   private Project project;

   Emploee() {
   }
   
   public Project getProject() {
      return project;
   }

}



Lets say that the "projectId" in the code below maps to an existing Project, but one for which no employees exists.
(The call to JPAManager.getInstance() returns a valid EntityManagerFactory (analogous to the commonly used "HibernateUtil" pattern used when running Hibernate without Java EE services))

We have the following code:
Code:


EntityManager em = JPAManager.getInstance().getEntityManager();
try {
   em.getTransaction().begin();
   Project project = em.find(Project.class, projectId);
   // project is here a project for which no employees are defined.
   project.getEmployees();  // returns null - not an empty list
   em.getTransaction().commit();
} finally {
   if (em.getTransaction().isActive()) {
      em.getTransaction().rollback();
   }
}


As commented - the project.getEmployees() getter here returns 'null' - not an empty list - is this what one would expect? One actually has to manually handle the "special case" where a relationship has no elements? (what one really would want is an empty list here). If yes, in order to make up for this (which can be a small nuicance when testing) is to initialize the list of employees for a project to an empty list like so:

Code:
   @OneToMany(mappedBy="project", cascade = CascadeType.ALL)
   private List<Employee> employees = ArrayList<Employee>();



However, when doing this, one stumbles into a problem when using hibernate as a persistence provider (and perhaps using others as well?)
If a persisted Employee instance is deleted using the entitymanager remove() and cosecutively persisted using the same entity manager, one receieves the infamous and badly documented:

Code:
Caused by: org.hibernate.HibernateException: Found two representations of same collection: Project.employees
    at org.hibernate.engine.Collections.processReachableCollection(Collections.java:176)
    at org.hibernate.event.def.FlushVisitor.processCollection(FlushVisitor.java:60)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:124)
    ...


For some reason, the collection is stuck somewhere in the hibernate session (a call to contains() on the entity manager correctly verifies that the entity indeed is gone from the manager), and no flush() or clear() on the entitymanager can remedy this. Not even getting a handle to the Hibernate session itself and clearing it directly helps (via the getDelegate() method on the entity manager). The only thing which helps is to create another entity manager.

Has anyone any neat solutions to these troubles? I would really like to create my entities with as few JPA-required tweaks as possible (like not initializing the employees list with an empty list - just to avoid the hibernate exception explained). Moreover, Hibernate is really the desired provider for me as it does not require any JVM agent to enable full lazy loading of mapped entities like for example is required by eclipselink.

I would really appreciate your thoughts on these issues! :)


Top
 Profile  
 
 Post subject: Re: Basic JPA @OneToMany / @ManyToOne mapping trouble
PostPosted: Sun Sep 27, 2009 7:12 am 
Newbie

Joined: Sat Sep 26, 2009 12:00 pm
Posts: 6
Allow me to clarify the problem:

Initializing a @OneToMany relationship with an empty list is allowed according to the JPA 1.0 spec. As stated in the previous post, this is also highly desireable. Thus, the following mapping is valid:
Code:
   @OneToMany(mappedBy="project", cascade = CascadeType.ALL)
   private List<Employee> employees = new ArrayList<Employee>();


However, the following sequence of events results in the HibernateException previously explained ("Found two representations of same collection"):
  • Obtain a (resource-local) entity manager factory, and create an EntityManager
  • Start a transaction
  • Delete a (previously persisted) Project entity (with an empty list of Employees) using the entity manager
  • Commit the transaction
  • Start a new transaction
  • Persist the (detached) Project entity again using the entity manager
  • Commit the transaction
  • The explained exception is thrown.

Is this a bug with hibernate? The explained sequence of events may seem a bit wierd (why delete an entity just to have it persisted again?), but clearly - this should be allowed?
As stated earlier, nothing helps but creating a new EntityManager to use for persisting the previously deleted entity.

Please help!!


Top
 Profile  
 
 Post subject: Re: Basic JPA @OneToMany / @ManyToOne mapping trouble
PostPosted: Mon Sep 28, 2009 4:57 am 
Newbie

Joined: Sat Sep 26, 2009 12:00 pm
Posts: 6
Bump


Top
 Profile  
 
 Post subject: Re: Basic JPA @OneToMany / @ManyToOne mapping trouble
PostPosted: Mon Sep 28, 2009 10:26 am 
Newbie

Joined: Sat Sep 26, 2009 12:00 pm
Posts: 6
An update on this issue;
Even though the HibernateException is thrown as previously explained, it seems like the entities have been persisted as though the persist() operation was applied successfully (this is also true if the mapped list was to contain elements (and even nested within those again, i.e. the operation was probably cascaded correctly the whole way through)).

Now surely, people must have exeprienced this issue - this scenario isn't that improbable, doesn't anyone have any insights to share on this issue? :)


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

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.