论坛首页 Java企业应用论坛

经常遇到collection with two open sessions 问题

浏览 26720 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-03-16  
最近经常遇到 下面这个异常
Illegal attempt to associate a collection with two open sessions; nested exception is org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions 



我感觉就是 一个 1:n 关系中,比如 论坛的主题和论坛的回复


如果在 一个 controller 方法中, 即想修改 主题的“标题”字段 ,又想修改 回复的“内容”字段 , 然后同时 调用doSave(主题) 和 doSave(回复) ,就会报这个异常。

下面是我 1 对应 的 hbm.xml文件中 相关代码
        <set name="backs" table="app_forum_topic_back" lazy="true" cascade="all" inverse="true">
            <key column="parentId"/>
            <one-to-many class="org.appfuse.model.ForumTopicBack"/>
        </set>


我不清楚 这样的需求 不 同时 调用doSave(主题) 和 doSave(回复) 还有什么别的办法? 大家怎么解决这个问题?


   发表时间:2007-03-17  

最近经常遇到 下面这个异常 ?

会不会是dao获取session有问题

0 请登录后投票
   发表时间:2007-03-17  
不能进行跨session的lazy loading,把操作放在一个session里面就能解决。
0 请登录后投票
   发表时间:2007-03-17  
其实问题在于你的两个操作是否是在一个事务里,通过查看spring的事务那部分代码可以得知,如果方法在事务中,那么方法中所有的session都是同一个,这个session和对应的transaction会组装成一个sessionHolder类然后放到当前线程中,如果不在一个事务中,那么每次调用dao都会得到一个新的session,这样两次得到同一个object会使这个object和两个session关联,具体的原因就是这样的,楼主不防对照着看一下,我觉得象楼主这个操作其实应该是放到同一个事务中的,在楼主的contraller不被包含在事务中,所以才会出现这个异常的吧,另,这个异常和1:N没有什么关系的,你可以查看一下spring的sessionfactoryutil类和hibernatetransactionmanager类就明白了,我可能讲的也不是很清楚
0 请登录后投票
   发表时间:2007-03-19  
ahuaxuan 写道
其实问题在于你的两个操作是否是在一个事务里,通过查看spring的事务那部分代码可以得知,如果方法在事务中,那么方法中所有的session都是同一个,这个session和对应的transaction会组装成一个sessionHolder类然后放到当前线程中,如果不在一个事务中,那么每次调用dao都会得到一个新的session,这样两次得到同一个object会使这个object和两个session关联,具体的原因就是这样的,楼主不防对照着看一下,我觉得象楼主这个操作其实应该是放到同一个事务中的,在楼主的contraller不被包含在事务中,所以才会出现这个异常的吧,另,这个异常和1:N没有什么关系的,你可以查看一下spring的sessionfactoryutil类和hibernatetransactionmanager类就明白了,我可能讲的也不是很清楚


你讲得很清楚,我现在事务确实不是 定义在 controller层,而是  参考 appfuse

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
		....
     </bean>
    
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="dao" class="org.appfuse.dao.hibernate.BaseDaoHibernate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="baseManager" class="org.appfuse.service.impl.BaseManagerImpl">
        <property name="dao" ref="dao"/>
    </bean>


是 dao 在事务控制中。  至于 你说那个解决办法我还没试验,不过感觉你说的有道理。


这个问题我现在已经解决,我是这么做的
//添加或修改主题
forumTopic.setTitle(formBean.getTitle());
....
forumTopic.setBacks(null);  //关键是加了这句话
forumManager.saveObject(forumTopic); 


//添加或修改回复
forumTopicBack.setContent(formBean.getContent());
....
 forumManager.saveObject(forumTopicBack);


就是 1操作完毕后,把 1种的 collection 设成 null, 然后再 操作 n. 现在是成功了。

事务控制在 controller 层上 真的比 控制在 dao层好么? 希望继续讨论
0 请登录后投票
   发表时间:2007-03-19  
引用
hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了。


再参考 ahuaxuan 朋友 说的, 那再看上面的引用,是不是意味着 事务控制的范围越广,一级缓存利用率就越高 ? 效率就越大呢 ?


因为session只要不关闭,就能利用 hibernate 一级缓存。那让session关得越晚,就可能更多的用一级缓存。

迫切想 明确这个问题。 大家怎么看 : session,事务,一级缓存 三者关系 。
0 请登录后投票
   发表时间:2007-03-19  
你可以看一下spring这块的源码,我觉得对hibernate的使用诠释的相当清晰。
只有在spring的实现中才是一个transaction范围内存在一个session,别把这个搞混了。
为了提高命中率也别在一级缓存的层面上作文章(建议二级缓存或者在应用层面上实现自己的缓存),如spring这样随开随关才是正途。
0 请登录后投票
   发表时间:2007-03-19  
JavaFlasher 写道
引用
hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了。


再参考 ahuaxuan 朋友 说的, 那再看上面的引用,是不是意味着 事务控制的范围越广,一级缓存利用率就越高 ? 效率就越大呢 ?


因为session只要不关闭,就能利用 hibernate 一级缓存。那让session关得越晚,就可能更多的用一级缓存。

迫切想 明确这个问题。 大家怎么看 : session,事务,一级缓存 三者关系 。

hibernate中,transaction来自session,一级缓存也在session中
引用
只有在spring的实现中才是一个transaction范围内存在一个session,别把这个搞混了。
其实不用spring也可以做到这一点,具体参考hibernate in action中的hibernateutil类,同spring一样,也是把这个session通过threadlocal放到thread中,只不过没有aop,就需要编程式事务了
0 请登录后投票
   发表时间:2007-03-19  
ahuaxuan 写道

引用
只有在spring的实现中才是一个transaction范围内存在一个session,别把这个搞混了。
其实不用spring也可以做到这一点,具体参考hibernate in action中的hibernateutil类,同spring一样,也是把这个session通过threadlocal放到thread中,只不过没有aop,就需要编程式事务了

我的意思是transaction和单个session没有必然联系,这只是spring的实现。
当然你自己也能这样实现。
0 请登录后投票
   发表时间:2007-03-19  
没有人说transaction和单个session有联系,即使在spring里也是一样,两者还是没有必然联系,transaction真正的来源是数据源
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics