注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

liangxh2008的博客

 
 
 

日志

 
 

spring Transaction Manager和hibernate session 吐血经验谈  

2010-05-12 20:33:24|  分类: java |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

关键字: spring transaction hibernate session

记录我在使用spring,hibernate的时候遇到的session,和事务管理的问题.
spring用一个OpenSessionInView的filter来处理session was closed的问题.这个大家并不陌生.
我 们项目当中的dao层有一个baseDao. 封装了一系列对持久化对象的操作方法.C,R,U,D 条件查询.分页查询.等等.而且baseDao当中的所有的find方法都是readOnly的,get和load直接调用的 hibernateTemplate的get和load.当然service层当中的事务管理也是使用spring的那个事务模板.
Java代码 复制代码
  1. <bean id="transactionManager"  
  2.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">   
  3.         <property name="sessionFactory">   
  4.             <ref local="sessionFactory" />   
  5.         </property>   
  6.     </bean>   
  7.        
  8.         
  9.     <bean id="txProxyTemplate" lazy-init="true" abstract="true"  
  10.         class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">   
  11.         <property name="transactionManager">   
  12.             <ref bean="transactionManager" />   
  13.         </property>   
  14.         <property name="transactionAttributes">   
  15.             <props>   
  16.                 <prop key="save*">PROPAGATION_REQUIRED</prop>   
  17.                 <prop key="del*">PROPAGATION_REQUIRED</prop>   
  18.                 <prop key="update*">PROPAGATION_REQUIRED</prop>   
  19.                 <prop key="create*">PROPAGATION_REQUIRED</prop>   
  20.                 <prop key="add*">PROPAGATION_REQUIRED</prop>   
  21.                 <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>   
  22.                 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>   
  23.                 <prop key="*">PROPAGATION_REQUIRED</prop>   
  24.             </props>   
  25.         </property>   
  26.     </bean>  
Java代码
  1. <bean id="transactionManager"  
  2.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  3.         <property name="sessionFactory">  
  4.             <ref local="sessionFactory" />  
  5.         </property>  
  6.     </bean>  
  7.       
  8.        
  9.     <bean id="txProxyTemplate" lazy-init="true" abstract="true"  
  10.         class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
  11.         <property name="transactionManager">  
  12.             <ref bean="transactionManager" />  
  13.         </property>  
  14.         <property name="transactionAttributes">  
  15.             <props>  
  16.                 <prop key="save*">PROPAGATION_REQUIRED</prop>  
  17.                 <prop key="del*">PROPAGATION_REQUIRED</prop>  
  18.                 <prop key="update*">PROPAGATION_REQUIRED</prop>  
  19.                 <prop key="create*">PROPAGATION_REQUIRED</prop>  
  20.                 <prop key="add*">PROPAGATION_REQUIRED</prop>  
  21.                 <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>  
  22.                 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>  
  23.                 <prop key="*">PROPAGATION_REQUIRED</prop>  
  24.             </props>  
  25.         </property>  
  26.     </bean>  
<bean id="transactionManager"    class="org.springframework.orm.hibernate3.HibernateTransactionManager">    <property name="sessionFactory">     <ref local="sessionFactory" />    </property>   </bean>          <bean id="txProxyTemplate" lazy-init="true" abstract="true"    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">    <property name="transactionManager">     <ref bean="transactionManager" />    </property>    <property name="transactionAttributes">     <props>      <prop key="save*">PROPAGATION_REQUIRED</prop>      <prop key="del*">PROPAGATION_REQUIRED</prop>      <prop key="update*">PROPAGATION_REQUIRED</prop>      <prop key="create*">PROPAGATION_REQUIRED</prop>      <prop key="add*">PROPAGATION_REQUIRED</prop>      <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>      <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>      <prop key="*">PROPAGATION_REQUIRED</prop>     </props>    </property>   </bean>  

以上配置都OK.
我遇到的问题有几个, 如下:
问题1,需要实现这样一个业务逻辑: 先把对象find出来.然后改变某个属性.然后在update. 在service当中就会写这样一个方法.changeOrder.在changeOrder当中先用dao的find.然后在用dao的update. 理论上是可行的.因为service的事务都是被spring的事务模板托管.而且changeOrder得到的connection是可写的.(因为spring的 事务模板根据对方法名的匹配来判断获得得connection类型).但是由于baseDao.当中的所有find方法都是 setReadyOnly(true). 这样.当在service执行任何find的时候.baseDao将强行把connection改为只读的.接下来在一个事务当中.任何update 和save动作都不能完成了.但是直接执行hibernateTemplate的get和load却不会出现这个问题.因为这个connection的属 性是由spring的openSessionInView来处理的.在request一过来的时候spring会绑定一个session.到request.直至request结束.(在这段过程当中如果不认为改变connection的readOnly的属性.这个connection将会从请求一开始到结束都是可以写入的.)

解决的办法就是在自己的dao当中将find方法重载.将readOnly改为false.

问题2, 有两个方法.一个是get对象.一个是find对象.同样也是直接调用baseDao的get和find方法.
当我对一个对象进行编辑操作的时候发现service当中的update是有效的. 但是我find出来的对象.在利用service当中的update来更新却发现没有任何异常.但是就是更新不了对象.
后 来才明白.get方法当中是没有对connection进行任何readOnly相关的操作.但是baseDao当中却设置了只读..这个时候又有一些疑 问了. action并没有进行事务管理.当先调用service的find方法(也就是调用了baseDao中的find方法).这一个事务已经提交了.然后在 继续调用service的update.为什么会更新不了对象?
原因就是在于OpenSessionInView.绑定的一个session 对象在这一次的request当中.所以.从一次request.开始到结束.这个request仅仅会操作当前的一个session对象. 尽管在action当中连续调用的两次service方法都有两个不同的事务范围.在一整个请求当中还是只存在一个session对象.
所以 第一个service的find方法执行完毕之后已经将当前request范围内的session改成了readOnly.以后的所有的service操 作都是只读的.后面的service一些save或者update方法都会失效.....这就是OpenSessionInView和事务之间的微妙关 系.

问题3,在ajax异步调用当中.经常也会出现这一系列的问题.其实原理大都是一样.因为ajax后来也是一个以.dwr结尾的 请求.在OpenSessionInView当中加入一个filtermapping 为 .dwr 这样它会拦截所有的.dwr请求.在所有的ajax操作当中会绑定一个session对象.

总结一下: OpenSessionInView是一个filter.它会为每一个request绑定一个session.任何接下来在这一次请求当中所有的 hibernate操作.都是基于当前请求的这个session的.任何service或者dao把当前的session对象改为了readOnly后. 接下来所有save or update操作将进行不了.尽管他们不是在一个service方法(不是在同一个事务当中进行).


BTW.service在很大程度上是可以和dao层混合到一起.这样可以节约很多代码.但是.也会带来维护的时候非常的负责.并且麻烦.特别是readOnly 和session was closed问题.会另你非常的沮丧.
dao实际上是不需要用transaction来管理的.真正需要事务的是项目当中的service层.理解才是最重要的.用好OpenSessionInView会给项目带来极大的方便.
  评论这张
 
阅读(824)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017