Here's one that has me perplexed. I'm trying to implement a basic Hibernate DAO structure, but am having a problem.
Here's the essential code:
int startingCount = sfdao.count();
sfdao.create( sf );
SecurityFiling sf2 = sfdao.read( sf.getId() );
sfdao.delete( sf );
int endingCount = sfdao.count();
assertTrue( startingCount == endingCount );
assertTrue( sf.getId().longValue() == sf2.getId().longValue() );
assertTrue( sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() ) );
assertTrue( sf.getSfTransactionNumber().equals( sf2.getSfTransactionNumber() ) );
It fails on the third assertTrue where it's trying to compare a value in sf to the corresponding value in sf2. Here's the exception:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.freightgate.domain.SecurityFiling_$$_javassist_7.getSfSubmissionType(SecurityFiling_$$_javassist_7.java)
at com.freightgate.dao.SecurityFilingTest.test(SecurityFilingTest.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
If you using Spring and JPA annotation, the simpliest way to avoid problem with session in lazy initialize is replaysing:
to
See my article. I had the same problem - LazyInitializationException - and here's the answer I finally came up with:
http://community.jboss.org/wiki/LazyInitializationExceptionovercome
Setting lazy=false is not the answer - it can load everything all at once, and that's not necessarily good. Example:
1 record table A references:
5 records table B references:
25 records table C references:
125 records table D
...
etc. This is but one example of what can go wrong.
--Tim Sabin
If you are managing the Hibernate session manually, you may want to look into sessionFactory.getCurrentSession() and associated docs here:
http://www.hibernate.org/hib_docs/v3/reference/en/html/architecture-current-session.html
We encountered this error as well. What we did to solve the issue is we added a lazy=false in the Hibernate mapping file.
It appears we had a class A that's inside a Session that loads another class B. We are trying to access the data on class B but this class B is detached from the session.
In order for us to access this Class B, we had to specify in the class A's Hibernate mapping file the lazy=false attribute. For example,
By default, all
one-to-many
andmany-to-many
associations are fetched lazily upon being accessed for the first time.In your use case, you could overcome this issue by wrapping all DAO operations into one logical transaction:
Another option is to fetch all LAZY associations upon loading your entity, so that:
should fetch the LAZY
submissionType
too:This way, you eagerly fetch all lazy properties and you can access them after the Session gets closed too.
You can fetch as many
[one|many]-to-one
associations and one "[one|many]-to-many" List associations (because of running a Cartesian Product).To initialize multiple "[one|many]-to-many", you should use Hibernate.initialize(collection), right after loading your root entity.
It seems only your DAO are using session. Thus a new session is open then close for each call to a DAO method. Thus the execution of the program can be resumed as:
By default, collection and association in an entity are lazy: they are loaded from the database on demand. Thus:
sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() )
is throwing an exception because it request a new loading from the database, and the session associated with the loading of the entity has already been closed.
There is two approaches to resolve this problem:
create a session to enclosed all our code. Thus it would mean changing your DAO content to avoid opening a second session
create a session then update (i.e. reconnect) your entity to this session before the assertions.
session.update(object);