I have a really strange problem here, and I totally donβt understand why this is happening.
The problem looks like this:
I have a class called "SmampiAccount" that contains 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 using 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; }
It works great as it is.
Now I wanted to add a new property to the mapping file in order to keep the link to the default email account:
<many-to-one name="defaultMailAccount" column="DEFAULT_MAIL_ACCOUNT_ID" />
Now I get an exception in the public method SmampiAccount loadSmampiAccount (long identifier) ββ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 is closed manually, and .commit() is not yet called (which usually closes the session). It is also not possible that a different method is used here, because I am creating a new hibernation session for each method call that is only for this method.
Edit
I added some debug information about the state of the open session:
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!