.... public void testCascadeUserAccount() { // get User User user = dao.get(1); assertNotNull(user); assertTrue(user.getId() == 1);
// add new account Account account = newAccount(); account.setUser(user); user.getAccounts().add(account); // OOPS! error was thrown here!! dao.save(user);
assertTrue(user.getAccounts().size() == 3);
// check the list List<Account> accounts = user.getAccounts(); assertNotNull(accounts); for (Accounts a : accounts) { log.debug("Account................" + a.toString()); assertTrue(a.getId() > 0); } } ....
An exception was thrown...
[emessaging] 2007-04-25 19:37:13 ERROR [main] LazyInitializationException.<init>(19) | failed to lazily initialize a collection of role: com.sample.model.User.accounts, no session or session was closed org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.sample.model.User.accounts, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350) at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97) at org.hibernate.collection.PersistentBag.size(PersistentBag.java:225) at com.g1.emessaging.dao.AccountDaoTest.testCascadeUserAccount(GatewayDaoTest.java:149) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at junit.framework.TestCase.runTest(TestCase.java:164) at junit.framework.TestCase.runBare(TestCase.java:130) at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:120) at junit.framework.TestSuite.runTest(TestSuite.java:230) at junit.framework.TestSuite.run(TestSuite.java:225) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:138) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:125) at org.apache.maven.surefire.Surefire.run(Surefire.java:132) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:290) at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:818)
but when I changed my test case into this, such that I queried again the user object to the database, and from there, assert that getAccounts().size() is equal to three, it runs fine.
.... public void testCascadeUserAccount() { // get User User user = dao.get(1); assertNotNull(user); assertTrue(user.getId() == 1);
// add new account Account account = newAccount(); account.setUser(user); //user.getAccounts().add(account); // OOPS! error was thrown here!! dao.save(user);
//assertTrue(user.getAccounts().size() == 3); // this will also cause error when not commented
// code changes, to get again the modified user from the db User modifiedUser = dao.get(1); assertNotNull(modifiedUser); assertEquals(modifiedUser.getAccounts().size() == 3);
// check the list List<Account> accounts = user.getAccounts(); assertNotNull(accounts); for (Accounts a : accounts) { log.debug("Account................" + a.toString()); assertTrue(a.getId() > 0); } } ....
Yes, basically you can get the size, because there are Proxy objects in the Collection, that only have the ids of the many records. It has no data.
If you try to add an object to the collection, or read an object from the collection, Hibernate will want to go to the database to load the data, because it was lazy loaded. But since you are no longer in a Unit of Work, you have no Sesson available, and therefore it cannot access the database anymore and throws a LazyInitializationException.