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.javaCode:
@ManyToMany(mappedBy="users")
private List<Group> groups;
Group.javaCode:
@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.javaCode:
@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.javaCode:
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.