私は本当に奇妙な問題を抱えています。なぜこれが起こっているのか、私は絶対に理解できません。Hibernate:決して閉じないで(手動)
問題は、次のようになります。
私は、電子メールアカウントのリストを保持している「SmampiAccount」と呼ばれるクラスを得ました。私はこの方法で、このクラスのインスタンスを取得
<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>
:
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;
}
ことがあるので、これは正常に動作マッピングファイルには、この(短縮)のように見えます。
は今、私はデフォルトの電子メールアカウントへの参照を保存するために、マッピングファイルに新しいプロパティを追加したい:今すぐ
<many-to-one name="defaultMailAccount" column="DEFAULT_MAIL_ACCOUNT_ID" />
、私はこの方法で例外を取得公共SmampiAccount loadSmampiAccountを(この行の長いID):
List<MailAccount> mailAccounts = smampiAccount.getMailAccounts();
スタックトレース:
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)
これはどのように可能ですか? セッションは手動で閉じられず、.commit()
はまだ呼び出されていません(通常はセッションを終了します)。 この1つのメソッドだけに専用のメソッド呼び出しごとに新しい休止状態のセッションを作成するので、別のメソッドがここで干渉しているとは考えられません。
編集
私は、セッションオープン状態にいくつかのデバッグ情報を追加しました:
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();
これは私を与える:
true
true
true
org.hibernate.SessionException: Session is closed!
奇妙に見えます。 loadメソッド( 'System.err.println(session.isOpen());やそれに類するもの)の呼び出し前後で、セッションの状態を調べることをお勧めします。別の質問:load()の前に手動でセッションを閉じると、スタックトレースは同等ですか? – waxwing
テスト目的のために、 ''に 'lazy =" false "'を追加すれば正常に動作しますか?また、どのHibernateのverisonを使用していますか? –
@waxwing元の投稿にデバッグ情報を追加しました。結果は私にとって非常に奇妙に見えます。また、 'session.load(...)'の前に 'session.close()'を追加しようとしました。それは再び私に "セッションが閉じられている"例外を与えます。 'session.load(...)'の呼び出しの下で 'session.close()'を動かせば、 'org.hibernate.LazyInitializationException:この行にはプロキシを初期化できませんでした - セッションはありません 'というメッセージが表示されます:' List mailAccounts = smampiAccount.getMailAccounts(); ' –
Timo