- 浏览: 57422 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
9976:
讲得很清晰详细,基本理解了~
JMS入门 -
robin35java:
这篇文章好,对于信号量进行了解释,并且扩展了线程的实现思考方式 ...
JAVA线程间通信问题 -
ds3783:
其实上述的问题总归起来还是架构设计不明确,Service层是否 ...
spring Transaction Manager和hibernate session 吐血经验谈 -
ivyloo:
好东西呀!谢谢了
JAVA基础
spring Transaction Manager和hibernate session 吐血经验谈
关键字: 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的那个事务模板.
以上配置都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会给项目带来极大的方便.
spring用一个OpenSessionInView的filter来处理session was closed的问题.这个大家并不陌生.
我们项目当中的dao层有一个baseDao. 封装了一系列对持久化对象的操作方法.C,R,U,D 条件查询.分页查询.等等.而且baseDao当中的所有的find方法都是readOnly的,get和load直接调用的hibernateTemplate的get和load.当然service层当中的事务管理也是使用spring的那个事务模板.
- <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>
<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会给项目带来极大的方便.
评论
1 楼
ds3783
2009-08-24
其实上述的问题总归起来还是架构设计不明确,Service层是否可以访问Session?
界面层是否能够访问Session?
如果前两个问题是Y的话,那么DAO层起什么作用,DAO层与Service层以及web层如何做到职责分离?
最后PO为什么要绑session(在PO中没有大字段的情况下)?
我们是不是要回到CMP的时代?
界面层是否能够访问Session?
如果前两个问题是Y的话,那么DAO层起什么作用,DAO层与Service层以及web层如何做到职责分离?
最后PO为什么要绑session(在PO中没有大字段的情况下)?
我们是不是要回到CMP的时代?
发表评论
-
POI操作EXCEL
2009-07-20 16:58 3128public class SummaryHSSF { ... -
JAVA线程间通信问题
2009-04-23 17:51 8274问题 在前一小节,介绍了在多线程编程中使用同步机制的重要性, ... -
JMS
2009-04-23 10:41 1685JMS编程知识 关键字: jms ... -
Spring AOP 2
2009-04-11 14:18 867Spring AOP高级篇(自动 ... -
Spring AOP
2009-04-11 14:17 973Spring AOP(2008-12-19 20:23:5 ... -
apache+tomcat配置
2009-04-10 17:48 2336apache+tomcat配置[转] 2007-10-27 ... -
apache+tomcat集群配置
2009-04-10 17:06 6843APACHE 2.2.8+TOMCAT6.0.14配置负载均衡 ... -
JMS 消息头
2009-04-09 23:28 2585深入掌握JMS(六):消息头 2009年03月31日 星期二 ... -
JMS topic
2009-04-09 23:26 3913深入掌握J ... -
深入掌握JMS(四):实战Queue
2009-04-09 23:24 1998Queue实现的是点到点模型,在下面的例子中,启动2个消费者共 ... -
深入掌握JMS(三):MessageListener
2009-04-09 23:22 55352009年03月31日 星期二 09:41 ... -
JMS例子
2009-04-09 23:19 3770深入掌握JMS(二):一个JMS例子 2009年03月31日 ... -
JMS入门
2009-04-09 23:17 20761. JMS基本概念 JMS( ... -
rmi 入门
2009-04-09 23:09 1139转]RMI实例入门(2009-02-26 ... -
java 23种模式代码
2009-04-09 02:07 144823种设计模式的代码版(Java) Posted on ... -
JAVA基础
2009-04-08 01:22 13321 【JAVA】JAVA相关基础知识 ... -
抽象工厂模式代码
2009-03-27 01:12 4112爪哇语言抽象工厂创立性模式介绍 工厂模 ... -
spring 事务传播机制
2009-03-26 19:29 1307Spring事务传播机制 PROPAG ... -
Spring声明式事务管理源码解读之事务提交
2009-03-26 19:27 1351/** *作者:张荣华(ahuaxuan) *2007-0 ...
相关推荐
可以对hibernate的 Session 和 Transaction 有更深入的认识 希望对一些概念比较模糊的人 有帮助
spring-hibernate-maven-transaction整合
NULL 博文链接:https://stewchicken.iteye.com/blog/938875
FactoryTalk Transaction Manager 用户手册,便于了解产品配置等
里面为一个演示spring事务传播机制的小demo。简单实现转账功能,通过添加注解调整传播级别,同时通过日志打印查看sql是否执行,在mysql中的数据是否发生了变化(操作提交还是回滚了)。
在spring+hibernate的框架中定时操作数据库,主要是拿到sessionFactory,不会出现no session 和transaction no-bound等问题,由sessionFactory完成对数据的操作,有些包是没有用的,有兴趣的可以自己删除掉
在使用maven开发web项目极大地方便了jar包的...oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one. 而且启动过程会暂停十几秒,在反复调试代码时很浪费时间
在准备整合Spring之前,也在网上看了各种配置。但是楼主心里还是很纠结,...楼主还是一步一步的来吧,感觉Spring操作Hibernate还是离不开DataSource,SessionFactory,Transaction这几个要素。 详细说明看我的博客文章。
Transaction tx1 = session1.beginTransaction(); // 先加载一个持久化对象 Customer customer = (Customer)session.get(Customer.class, new Long(1)); session.delete(customer); // 计划执行一个delete语句
spring-transaction.jar.zip
Learn how to use the core Hibernate APIs and tools as part of the Spring Framework. This book illustrates how these two frameworks can be best utilized. Other persistence solutions available in Spring...
spring 3.2.0+hibernate 4.1.6+struts2整合需要的jar包 的目录 antlr-2.7.7.jar aopalliance-1.0.jar asm-3.3.jar asm-commons-3.3.jar aspectjweaver-1.5.3.jar bonecp-0.7.1.RELEASE.jar cglib-2.1.3.jar ...
Spring提供了org.springframework.orm.hibernate3.HibernateTemplate类和org.springframework.orm.hibernate3.HibernateCallback接口来方便和Hibernate整合。 HibernateTemplate类封装了Hibernate的主要类,它提供了...
Spring在Transaction事务传播行为种类,希望对大家有所帮助
Could not roll back Hibernate transaction.doc
一个简单的spring+hibernate+mysql 事务实例
org.springframework.transaction-3.2.2.RELEASE最新版本
NULL 博文链接:https://wsjjasper.iteye.com/blog/1570448
该软件依赖包,为实例spring aop实现Hinernate事务操作软件包
org.springframework.transaction-3.0.0.M4.jar