[jboss-user] [JBoss Seam] - failed to lazily initialize a collection

quilian do-not-reply at jboss.com
Wed Apr 25 11:55:45 EDT 2007


Hello again!

I managed to get my other problems working by using a SMPC (thanks pete).
however i now stumble accross the 1:n relationship of my entities Benutzer and Gruppe.

I declared the Benutzer as following:

  | @Entity
  | @Name("benutzer")
  | @Table(name = "benutzer")
  | public class BenutzerImpl implements Serializable, Benutzer {
  | 
  | 	private static final long serialVersionUID = -2113540391643036310L;
  | 	private Long id;
  | 	private Integer version;
  | 	private String name;
  | 
  | 	GruppeImpl gruppe;
  | 	
  | 	@Logger
  | 	Log log;
  | 
  |        @Override
  |        public boolean equals(Object object) {
  |           if (object instanceof BenutzerImpl) {
  |     	      BenutzerImpl other = (BenutzerImpl) object;
  |          
  |              return (this.getId()==other.getId());
  |           }
  |           return false;
  |        }
  | 
  | 	@Id
  | 	@GeneratedValue
  | 	public Long getId()
  | 	public void setId(Long id)..
  | 	@Version
  | 	public Integer getVersion()...
  | 	@SuppressWarnings("unused")
  | 	private void setVersion(Integer version)..
  | 
  | 
  | 	@ManyToOne(optional = true)
  | 	@JoinColumn(name = "gruppe", nullable = true)
  | 	public GruppeImpl getGruppe() {
  | 		return gruppe;
  | 	}
  | 	
  | 	@Transactional
  | 	public void setGruppe(GruppeImpl aGruppe) {
  | 
  | 		if (gruppe != null)
  | 		{
  | 
  | 			gruppe.removeBenutzer(this);
  | 
  | 			gruppe = aGruppe;
  | 
  | 			if (gruppe != null) {
  | 
  | 				gruppe.addBenutzer(this);
  | 			}			
  | 		}
  | 		else
  | 		{
  | 			gruppe = aGruppe;
  | 		}		
  | 	}
  | }
  | 


and the Gruppe like that:

  | 
  | @Entity
  | @Name("gruppeImpl")
  | @Table(name = "gruppen")
  | public class GruppeImpl implements Serializable, Gruppe {
  | 	@Logger
  | 	Log log;
  | 
  | 	private static final long serialVersionUID = 2106790568007992821L;
  | 
  | 	private Long id;
  | 	private Integer version;
  | 	private String name;
  | 	private Boolean status;
  | 
  | 	private List<BenutzerImpl> someBenutzer;
  | 
  | 
  |    @Override
  |    @Transient   
  |    public boolean equals(Object object) {
  |       if (object instanceof GruppeImpl) {
  |     	  GruppeImpl other = (GruppeImpl) object;
  |          
  |          return (this.getId()==other.getId());
  |       }
  |       return false;
  |    }
  | 
  | 
  | 	@OneToMany(mappedBy = "gruppe")
  | 	@Transactional
  | 	public List<BenutzerImpl> getBenutzer() {
  | 		return someBenutzer;
  | 	}
  | 
  | 	public void setBenutzer(List<BenutzerImpl> newBenutzerList) {
  | 		
  | 		this.someBenutzer = newBenutzerList;
  | 	}
  | 
  | 	@Transactional
  | 	public void addBenutzer(BenutzerImpl benutzer) {
  | 		if (this.someBenutzer == null) {
  | 			this.someBenutzer = new ArrayList<BenutzerImpl>();
  | 		}
  | 		if (!this.someBenutzer.contains(benutzer))
  | 			this.someBenutzer.add(benutzer);
  | 	}
  | 
  | 	@Transactional
  | 	public void removeBenutzer(BenutzerImpl benutzer) {
  | 		if (this.someBenutzer == null)
  | 		{
  | 			return;
  | 		}
  | 		this.someBenutzer.remove(benutzer);
  | 	}
  | ...
  | }
  | 


The whole stuff in english:
If the Benutzer gets a new Gruppe he must update the corresponding List Gruppe.getBenutzer(). Else the java object gruppe doesnt know that something happened to him. Therefore i extended the simple setter Benutzer.setGruppe() to remove/add from old/new Gruppe.Im not sure if hibernate or javax or anything else could possibly do that for me, knowing that i want a 1:n relationship. i only do the update if the property gruppe is already set, because hibernate itself calls the getter on initialization of the Benutzer.

I also annotated the functions setGruppe, addBenutzer and removeBenutzer as @Transactional, because i want the operation to be in one transaction, hence rolled back completely if an error occurs. is that correct?

If i choose another Gruppe and submit the form i get:

  | 17:35:52,468 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: com.mobilanten.mowita.werkbank.GruppeImpl.benutzer, no session or session was closed
  | org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mobilanten.mowita.werkbank.GruppeImpl.benutzer, no session or session was closed
  |         at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
  |         at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
  | ...
  | 


I debugged and found out that both the new and the old Grupp have a session attribute with two different persistance contexts that referer to the same hibernate.session. By the time of execution of Benutzer.setGruppe() the session of the old Gruppe is marked as closed.

Why are there 2 PCs ? i thought there'd only be this one (components.xml)

  |    <core:managed-persistence-context name="mowitaEntityManager"
  | 			    auto-create="true"
  |                persistence-unit-jndi-name="java:/mowitaWerkbankEntityManagerFactory"/>
  | 

injected like that (GruppenManager and BenutzerManager):

  | 	@In
  | 	private EntityManager mowitaEntityManager;
  | 

I thought the SMPC would be application global....

Thanks for any help!
Tobias Kilian

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4040654#4040654

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4040654



More information about the jboss-user mailing list