[讨论]Spring中事务管理与Hibernate自带事务管理冲突的一个问题

场景是这样:
    有个提交申请单的操作,需三个动作:新增申请记录表记录、新增申请详单表记录,整个过程需完整,才能提交事务,其中一个过程失败,则需回到操作前状态,采用的是Spring声明式事务配置,但新增申请详单表记录时,由于插入数据量较大,发现用默认的HibernateTemplate里的save方法一条一条记录添加速度较慢,就使用了Hibernate批量插入,发现如果过程无错误,也会提示一个错误:java.lang.IllegalStateException: No value for key [org.hibernate.impl.SessionFactoryImpl@12421db] bound to thread [http-8080-Processor20]
,查了下估计是由于批量插入那边用了Hibernate自带的事务管理,释放了Hibernate下的session,和Spring配置的事务管理有冲突,有没有可以支持Spring自带事务管理,并且支持批量插入大量数据的方法,请教大家如何解决呢?


附上大致代码:

 

 

 

申请Service实现类大致Java代码:

 

 

public void applyCard(CardInfo cardInfo, List<CardDetail> cardDetails){
    //新增申请记录表记录
    applyDAO.saveCardInfo(cardInfo);
    //新增申请详单表记录
    applyDAO.batchSaveCardDetail(cardDetails);
}

 

申请applyDAO实现类的batchSaveCardDetail方法(Hibernate批量插入):

 

public void batchSaveCardDetail(List<TCardInfo> cardDetails) {
    Session session = this.getSession();
        Transaction tx=null;
            try{
               tx=session.beginTransaction();
               for(int i=0;i<cardDetails.size();i++){
                    session.save(cardDetails.get(i));
                    if(i%50 == 0){
                        session.flush();
                            session.clear();
                    }
                }
              tx.commit();//提交事务
            }catch(Exception ex){
                ex.printStackTrace();
                tx.rollback();//出错则回滚
            }finally{
                session.close();//关闭session
            }
}

Spring相关配置如下:

 

<!-- 应用的Spring里的Hibernate事务管理 -->
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置事务拦截器-->
<bean id="transactionInterceptor"
    class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager" />
    <property name="transactionAttributes">
        <props>
            <prop key="applyCard">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>
<!-- 根据事务拦截器为目标bean自动创建事务代理 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
        <list>
            <value>applyService</value>
        </list>
    </property>
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
</bean>
<!-- 申请Service -->
<bean id="applyService" class="service.impl.ApplyServiceImpl">
    <property name="applyDAO" ref="applyDAO"/>
</bean>

  

 

 

[quote]# getHibernateTemplate().execute(new HibernateCallback(){

public Object doInHibernate(Session session)

throws HibernateException, SQLException {

return (DataDictionary)session.createQuery("find DataDictionary d where d.category=? and d.code=?")

.setParameter(0, category)

.setParameter(1, code);

}

}); [/quote]

你那问题我没找到,,不过提示你一下,,
Hibernate的功能都可以通过HibernateTemplate实现。
execute就是一个被spring事务管理的回调方法,其中的操作与Hibernate完全相同

你是不是找错了原因。。
从错误上来看,原因是你保存的对象没有设置ID,你是不是保存的对象没有设置ID,而是通过触发器产生ID的呀。。。

[quote]saveOrUpdateAll(Collection entities)可否用于这个需要批量更新并交由Spring事务管理的地方呢[/quote]

这个东西并不是指提交,只不过是一堆的saveorupdate的集中的写法而已。。
对于Hibernate来说,批量提交有两种方式,一个是SQL的批量提交,它把一批SQL语句一起提交,主要是在配置文件中配置hibernate.jdbc.batch_size。然后程序中使用
[code="java"]if(i%50==0) //以每50个数据作为一个处理单元
...{
session.flush(); //保持与数据库数据的同步
session.clear(); //清除内部缓存的全部数据,及时释放出占用的内存
}[/code]
这种方式是一种。。
另一种就是bulkupdate/bulkdelete。
这个是发送HQL语句delete from table;这个方式的代价是执行完后直接清空缓存。。

你好,我也出现这个问题了,数据可以成功保存,就是报错,No value for key session is closed,

请问楼主怎么解决的啊??