场景是这样:
有个提交申请单的操作,需三个动作:新增申请记录表记录、新增申请详单表记录,整个过程需完整,才能提交事务,其中一个过程失败,则需回到操作前状态,采用的是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(){
你那问题我没找到,,不过提示你一下,,
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,
请问楼主怎么解决的啊??