lazy-fetch中的奇怪会话错误

时间:2011-03-17 16:58:35

标签: java hibernate spring transactions

错误为failed to lazily initialize a collection, no session or session was closed

有很多人问过几乎相同的问题,但分辨率并不那么直观。并且,我认为有必要发布另一个问题来描述这个奇怪的错误信息:

(我不会在这里粘贴源代码,因为它太长了。)

DEBUG [main] (AbstractPlatformTransactionManager.java:365) - Creating new transaction with name [com.bee32.plover.orm.feaCat.FeaturePlayer.tcList]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG [main] (HibernateTransactionManager.java:493) - Opened new Session [org.hibernate.impl.SessionImpl@19006c9] for Hibernate transaction
DEBUG [main] (HibernateTransactionManager.java:523) - Not preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@19006c9]
DEBUG [main] (HibernateTemplate.java:397) - Found thread-bound Session for HibernateTemplate
Hibernate:    /* criteria query */ select 
    ...

ERROR [main] (LazyInitializationException.java:42) - failed to lazily initialize a collection, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed
  at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    ...
  at java.util.HashSet.<init>(HashSet.java:116)
    ...
  at org.hibernate.loader.Loader.list(Loader.java:2124)
    ...
  at org.springframework.orm.hibernate3.HibernateTemplate$5.doInHibernate(HibernateTemplate.java:590)
  ...

DEBUG [main] (HibernateTemplate.java:422) - Not closing pre-bound Hibernate Session after HibernateTemplate
DEBUG [main] (AbstractPlatformTransactionManager.java:843) - Initiating transaction rollback
DEBUG [main] (HibernateTransactionManager.java:672) - Rolling back Hibernate transaction on Session [org.hibernate.impl.SessionImpl@19006c9]
DEBUG [main] (HibernateTransactionManager.java:734) - Closing Hibernate Session [org.hibernate.impl.SessionImpl@19006c9] after transaction

如您所见,当触发了lazy-fetch时,发生了错误,已经有一个线程绑定会话,并且在事务回滚之前它尚未关闭。

那么,为什么报告有no session or session was closed

修改 相关来源:

@Transactional
public void tcList() {
    for (Cat cat : dao.list()) {
        System.out.println("Saved cat: " + cat);
    }
}

3 个答案:

答案 0 :(得分:2)

该线程有一个绑定的会话,但是该会话管理的catList是不是?可能已经通过hibernate模板在dao.list()内部关闭了会话,该模板负责样板代码。

解决问题的一种方法是在返回列表之前在dao.list()函数内调用list.get(0).someGetter()。这将使用实际值填充列表,并且不应导致延迟初始化异常。如果Cat由延迟初始化的其他对象组成,那么您也应该在它们上面调用getter属性,以防您想要使用这些属性。

另外,尝试删除dao.list()方法中的任何Transactional注释(如果有)。使用调用函数创建的事务,而不是使用Propagation_Required属性。如果您在dao.list()上使用了@Transactional,那么事务管理器可能会在从此函数返回时触发transaction.commit()/ session.close(),因此catList成为一个分离的实体,其中所有的猫都是仍然代理。

答案 1 :(得分:0)

实体可能与会话分离,而懒惰加载集合只是一个代理?如果要使用它,需要将其合并到会话中吗?

答案 2 :(得分:0)

这意味着您正在尝试从会话中加载/初始化集合。可能你必须维持会话活着,直到你完成你的操作.....意味着你必须使用一些粘合代码管理你的会话资源... ppl会建议在实体的set方法中初始化延迟集合。使用懒惰的提取就像一个热切的提取。保持会话,直到操作可能是最好的方式....