I got a really weird problem here and I absolutely cannot understand why this is happening.
The problem looks like this:
I got a class called "SmampiAccount" which holds a list of email accounts. The mapping file looks like this (shortened):
<hibernate-mapping>
<class name="com.smampi.web.model.account.SmampiAccount" table="SMAMPIACCOUNT">
<id name="id" type="long" access="field">
<column name="SMAMPI_ACCOUNT_ID" />
<generator class="native" />
</id>
<bag name="mailAccounts" table="MAILACCOUNTS" lazy="false" inverse="true">
<key column="SMAMPI_ACCOUNT_ID"></key>
<one-to-many class="com.smampi.web.model.mail.account.MailAccount"/>
</bag>
</class>
</hibernate-mapping>
I get instances of this class through this method:
public SmampiAccount loadSmampiAccount(long id) throws FailedDatabaseOperationException {
SmampiAccount smampiAccount = null;
Session session = null;
Transaction transaction = null;
try {
session = getSession();
transaction = session.beginTransaction();
smampiAccount = (SmampiAccount) session.load(com.smampi.web.model.account.SmampiAccount.class, id);
List<MailAccount> mailAccounts = smampiAccount.getMailAccounts();
doSomething(mailAccounts);
transaction.commit();
} catch (Exception e) {
rollback(transaction);
closeSession();
throw new FailedDatabaseOperationException(e);
} finally {
closeSession();
}
return smampiAccount;
}
private Session getSession() {
if (_session == null) {
_session = getSessionFactory().openSession();
}
if (_session.isOpen() == false) {
_session = getSessionFactory().openSession();
}
return _session;
}
This works fine as it is.
Now, I wanted to add a new property to the mapping file in order to save a reference to a default email account:
<many-to-one name="defaultMailAccount" column="DEFAULT_MAIL_ACCOUNT_ID" />
Now, I get an exception in the method public SmampiAccount loadSmampiAccount(long id) in this line:
List<MailAccount> mailAccounts = smampiAccount.getMailAccounts();
Stacktrace:
org.hibernate.SessionException: Session is closed!
at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
at org.hibernate.impl.SessionImpl.getPersistenceContext(SessionImpl.java:1954)
at org.hibernate.event.def.DefaultPostLoadEventListener.onPostLoad(DefaultPostLoadEventListener.java:49)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:250)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
at org.hibernate.loader.Loader.doQuery(Loader.java:857)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2037)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:86)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:76)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3293)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:147)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1090)
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:1026)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.smampi.web.model.account.SmampiAccount_$$_javassist_19.getMailAccounts(SmampiAccount_$$_javassist_19.java)
How is this possible?
The session gets not closed manually and .commit() isn't called yet (which would normally close the session).
It's also not possible that another method is interfering here because I create a new hibernate session for each method call which is dedicated just for this one method.
Edit
I added some debug info on the session open status:
session = getSession();
System.err.println(session.isOpen());
transaction = session.beginTransaction(); // 1 (true)
System.err.println(session.isOpen()); // 2 (true)
smampiAccount = (SmampiAccount) session.load(com.smampi.web.model.account.SmampiAccount.class, id);
System.err.println(session.isOpen()); // 3 (true)
List<MailAccount> mailAccounts = smampiAccount.getMailAccounts(); // Throws exception that session is closed
doSomething(mailAccounts);
System.err.println(session.isOpen()); // 4 (not called)
transaction.commit();
This gives me:
true
true
true
org.hibernate.SessionException: Session is closed!
System.err.println(session.isOpen());or something like that). Another question: if you manually close the session before load(), is the stack trace equivalent? - waxwinglazy="false"to the<many-to-one>? Also, which verison of Hibernate are you using? - matt bsession.close()BEFORE thesession.load(...)call. That again gives me a "Session is closed" exception. If I move thesession.close()below thesession.load(...)call, I getorg.hibernate.LazyInitializationException: could not initialize proxy - no Sessionin this line:List<MailAccount> mailAccounts = smampiAccount.getMailAccounts();- Timo Ernstlazy="false"to<many-to-one>had no effect. I useHibernate 3.6.3.Finalwithmysql-connector-java-3.0.10-stableandC3P0. - Timo ErnstsmampiAccount.getMailAccounts();from your code sample? Are you using any other libraries in getting the Hibernate session, such as Spring, or any form of AOP? How about trying to upgrade Hibernate to a newer 3.6.x release, such as 3.6.5? Perhaps a bugfix addresses this. - matt b