-->
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: Failed to lazily initialize a collection of role?
PostPosted: Fri Jun 25, 2010 7:22 pm 
Newbie

Joined: Tue Jun 01, 2010 10:18 am
Posts: 15
Hello to all!

I have a problem with my Hibernate 3.5.3 and Spring 3.0.3. application. The error is this one:
Quote:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mydomain.myproject.data.domain.User.groups, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)
at com.mydomain.myproject.data.services.PersonServiceImpl.updatePerson(UserServiceImpl.java:45)
at com.mydomain.testing.UserTest.testUpdateUser(UserTest.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


I found this problem many times, but I did not get it solved.

I have a n:m (manytomany - bidirectional with a join table) relation between groups and users.
User.java
Code:
@ManyToMany(mappedBy="users")
private List<Group> groups;


Group.java
Code:
@ManyToMany
@JoinTable(name = "Group_User",
    joinColumns = {@JoinColumn(name="group_id", referencedColumnName="id")},
    inverseJoinColumns = {@JoinColumn(name="user_id", referencedColumnName="id")}
)
private List<User> users;


I can solve the problem if I do a FetchType EAGER and a Fetch SELECT.
But I do not want to do this, because this is only a part of my database structure and loading all thins eager, this would be crazy. And in my case with the n:m relation I get for example all groups, and the groups have a list of users, and the users have groups, and so on... not good :-)

The error is thrown by my JUnit / DbUnit test class:
UserTest.java
Code:
@Test
public void testUpdateUser() {
   List<User> users = service.getAllUsers();
   User user = users.get(0);

   // change & save user
   user.setEmail("updateMail@test.com");

   // HERE IS THE ERROR TRACE
   service.updateUser(user);

   // ...
}

The method "updateUser(user)" is the problem, which is defined in my service class:
UserServiceImpl.java
Code:
   public void updateUser(User u) {
      List<Group> groups= u.getGroups();
      Iterator<Group> iterator = groups.iterator();
      while (iterator.hasNext()) {
         Group group = iterator.next();
         boolean update = false;
         if (group.getUsers().contains(u)) {
            if (!u.getGroups().contains(group)) {
               // grouphas this user, but userdoes not have this groupanymore
               // -> delete group from user
               group.getUsers().remove(u);
               update = true;
            }
         } else {
            // groupdoes not have this user, should be added
            group.getUsers().add(u);
            update = true;
         }

         if (update) {
            groupDao.updateGroup(group);
         }
      }
      userDao.updateUser(u);
   }

The "iterator" line throws the error.
What will I do here with the groups (perhaps there is a better solution):
I have users which have groups. Now I want for example add or delete a group to a user (this is done in the frontend (Adobe Flex)).
So I do in the frontend a user.getGroups().add(...) or user.getGroups().remove(...) and the I call the service MyService.updateUser(user);
And now I update the user and I will get all the groups from the database (this is what I done here and throws the error!) and compare which entries in the joined table "Group_User" should be removed or added.

Perhaps it is possible to do this in another way and so I have no problems with the lazy/eager loading? Or what should I do?

Thanks a lot in advance for your help & Best Regards.


Last edited by PHANTOMIAS on Sun Jun 27, 2010 2:23 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Failed to lazily initialize a collection of role?
PostPosted: Sun Jun 27, 2010 1:59 pm 
Newbie

Joined: Mon Jun 21, 2010 1:36 pm
Posts: 14
Hi,

You might be getting this error because you probably had lazy="true", the default setting on the user--> group association. This will try to load a group object through its proxy when you try to access it. When the proxy is accessed, the session should be available, otherwise it would throw the LazyInitializationException.

Quote:
So I do in the frontend a user.getGroups().add(...) or user.getGroups().remove(...) and the I call the service MyService.updateUser(user);


Where are you opening and closing the Hibernate sessions? Is it in DAOs? From the above line from your post, I think that the error should have come up when you called user.getGroups.add() (or remove) in the frontend. If you can capture the stack trace showing the origin of error in your code, it would help.

How are you implementing your service? Is it an EJB, Web Service or a local POJO? If EJB or Web service are you hosting it on a remote machine (different from the presentation logic)?

-BJ


Top
 Profile  
 
 Post subject: Re: Failed to lazily initialize a collection of role?
PostPosted: Sun Jun 27, 2010 2:23 pm 
Newbie

Joined: Tue Jun 01, 2010 10:18 am
Posts: 15
Thanks a lot for your reply. Yes, as you can see, my annotations @manytomany has not a FetchType EAGER and the default value for @manytomany is LAZY.

IN this line is the cause of the error:
Code:
Iterator<Group> iterator = groups.iterator();


I have a HibernateUtility:
Code:
public class HibernateUtil {
   private static final SessionFactory sessionFactory;
   static {
      try {
         sessionFactory = new AnnotationConfiguration().configure("/hibernate.cfg.xml").buildSessionFactory();
      }
      catch (Throwable ex) {
         System.err.println("Initial SessionFactory creation failed. " + ex);
         throw new ExceptionInInitializerError(ex);
      }
   }
   public static SessionFactory getSessionFactory() {
      return sessionFactory;
   }
}

And in the DAO implementations always this type:
Code:
   public void removeGroup(int groupId){
      Group g = findGroupById(groupId);

      SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
      Session sess = sessionFactory.getCurrentSession();

      Transaction tx = sess.beginTransaction();
      sess.delete(g);
      sess.flush();
      tx.commit();
   }

So what can I do to solve this problem?

Best Regards


Top
 Profile  
 
 Post subject: Re: Failed to lazily initialize a collection of role?
PostPosted: Mon Jun 28, 2010 2:13 pm 
Newbie

Joined: Mon Jun 21, 2010 1:36 pm
Posts: 14
I am not sure if I understood your implementation completely. My understanding is that your session is getting created/flushed/closed in DAO itself. So, it is not available at the time you called groups.iterator() and so the LazyIntializationException. Based on this, I would suggest the following:

1. As your service method updateUser(User u) needs to work on u.groups, add a method to your UserDAO called getUserWithGroups(Long u.id) which will fetch User along with its Groups (eager fetch). The scenario you are implementing genuinely requires Groups within a User. So, I think Eager fetch is really needed here.

And then probably you know the rest.....

Put the following as the first statement of your updateUser() service method.
User ug = UserDAO.getUserWithGroups(Long u.id)

and then your code:

List<Group> groups = ug.getGroups();
Iterator<Group> iterator = groups.iterator();
:
:

2. The other approach might be to use OSIV hibernate pattern. Personally, I am not a big fan of this.

Regards,
BJ


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.