关于Spring4+Hibernate4架构升级-整合的细节处理-由nested transactions not supported错误解决引申到事务嵌套问题处理
2018-03-21 00:00
633 查看
关于Spring4+Hibernate4架构升级-整合的细节处理-由nested transactions not supported错误解决引申到事务嵌套问题处理
本着系统稳定的原则,选择了 Spring5 和 Hibernate5版本的第一级版本Spring4+Hibernate4做开发
由于此处错误处理,毁三观,耽误了比较长的时间,给自己了一个深刻的教训。颠覆了自己解决问题的期望和方式,很有效果,借以成文,以瞻后效。
架构升级之后,问题接二连三而来,犹如打怪升级。
当百度第一页的关联问题无法解决的时候,对着堆栈看程序的错误执行流程是最有效的。
DEBUG模式下,有的看第一个错误,有的看最后一个错误。我喜欢从下往上看,从下往上翻,翻到上面才是最后一个最终的错误。而错误的引发,往往在于全部的流程,在于之前的第一个报错,而最后一个错误提示,只不过是引起了程序的中断,于你真正想要解决的错误而言,真真正正的南辕北辙,驴唇不对马嘴。
Hibernate本身不支持DBCP了,而DBCP升级的二代效果,
我感觉还不错,所以就是她了,比较轻,参数设置也给力多了啊。
下述错误细节重点问题
即使二者的数据库连接配置有冗余,也没有影响到系统的运行。
但是,S4H4必须消除相关配置信息的冗余。
否则报错 - java.lang.UnsupportedOperationException: Not supported by BasicDataSource
交给Spring管理是最灵活和明智的选择。
而且,Hibernate并不支持DBCP,其提供的数据源定制接口的实现过于复杂和无聊,纯粹浪费感情。
果断,砍掉Hibernate的相关内容配置。
除了下述几个配置之外,可以保留,但是保留了也没有什么意思,还是别让他管了,费劲
下面是我的Spring 数据库设计,我喜欢这么玩,感觉代码还算OK
OK,事务管理器不用多说,非她莫属
这上边,一个负责Service层的声明式事务处理
一个负责DAO层的事务处理,以简化操作
都去open了,还要Spring简化处理个毛啊。
此处在整合中,坑比较多,
但是,最重要的只有一点 -
在H3中是 - org.springframework.orm.hibernate3.SpringSessionContext
如果没有配置此项,在与Spring整合的时候,必定报错 -
可能的错误是 - org.hibernate.HibernateException: save is not valid without active transaction
有了此项配置,才有了与Spring整合的可能性,
其它的说明。比如,必须开启和提交事务才能操作、jta云云,不多说了。
交给Spring去管理就OK了。
又回到上面的提示 - 这个错误是最终的错误,早已南辕北辙了。
首先需要说明的是,并非是Spring的事务处理的问题,而是S4比起S3代码严谨的多。
在S3中很少会提示这个错误的,
我的项目未升级前,全部正常运行,升级之后,报的这个错误非常的奇怪,因为配置本身都是类似的。
网上的答案也是五花八门。
如果涉及到底层框架的执行的话,参考意义几乎为0。
因为事务不是我自己做的,我根本不知道到底能不能在某个时刻真正的执行,想了好久,不知所云。果断打断点,看代码。
我注意到了两点,执行目标方法前,执行了一个aspect,执行了一个advisor
代码中,事务开启之后,再次开启了,就报了这个错误。
问题涉及两点,
一是事务的传播属性为默认,
二是执行方法只有一个,但是涉及到的切面很多,再带上声明式事务的advisor。
为什么会开启两次?
去排查aspect方法,果然发现了!
有切面类手动处理了事务,去操作数据库
由于方法单一,并未考虑Spring声明式
考虑的话,事务嵌套的问题可能会更加严重。
由此,总结出一点,
在Spring的执行流程中,
默认传播属性的执行中,
session一直存在,那么,这个session获取的事务,只要有一处完成了开启,那么后期处理的时候,全部都是开启的。无需再次开启。否则就会引起事务嵌套问题而报错。
问题的关键在于分清楚,到底谁是目标方法,其它的切面以及advisor的执行时机。
当然,这只是当前情境下的一种解决方案,仅供参考。
如需要转载
请注明文章出处
https://my.oschina.net/u/3032872/blog/1648364
谢谢~
本着系统稳定的原则,选择了 Spring5 和 Hibernate5版本的第一级版本Spring4+Hibernate4做开发
由于此处错误处理,毁三观,耽误了比较长的时间,给自己了一个深刻的教训。颠覆了自己解决问题的期望和方式,很有效果,借以成文,以瞻后效。
架构升级之后,问题接二连三而来,犹如打怪升级。
当百度第一页的关联问题无法解决的时候,对着堆栈看程序的错误执行流程是最有效的。
DEBUG模式下,有的看第一个错误,有的看最后一个错误。我喜欢从下往上看,从下往上翻,翻到上面才是最后一个最终的错误。而错误的引发,往往在于全部的流程,在于之前的第一个报错,而最后一个错误提示,只不过是引起了程序的中断,于你真正想要解决的错误而言,真真正正的南辕北辙,驴唇不对马嘴。
Hibernate本身不支持DBCP了,而DBCP升级的二代效果,
我感觉还不错,所以就是她了,比较轻,参数设置也给力多了啊。
下述错误细节重点问题
1、关于数据库处理
我只能说S4H4 比起 S3H3严谨的多,之前随意配置,无所谓。即使二者的数据库连接配置有冗余,也没有影响到系统的运行。
但是,S4H4必须消除相关配置信息的冗余。
否则报错 - java.lang.UnsupportedOperationException: Not supported by BasicDataSource
交给Spring管理是最灵活和明智的选择。
而且,Hibernate并不支持DBCP,其提供的数据源定制接口的实现过于复杂和无聊,纯粹浪费感情。
果断,砍掉Hibernate的相关内容配置。
除了下述几个配置之外,可以保留,但是保留了也没有什么意思,还是别让他管了,费劲
<!-- <property name="hibernate.connection.isolation">50</property> <property name="hibernate.connection.autocommit">50</property> <property name="hibernate.connection.release_mode">50</property> <property name="hibernate.connection.datasource">50</property> - JNDI配置 --> <property name="hibernate.connection.pool_size">50</property>
下面是我的Spring 数据库设计,我喜欢这么玩,感觉代码还算OK
<!-- Spring与数据库设计 --> & 7fe0 lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <!-- 引入prperties配置文件 - DBCP --> <value>classpath:dbcp.properties</value> </property> </bean> <!-- 数据源的相关实际参数的配置和获取 --> <!-- DBCP数据库连接池参数配置 --> <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="${jdbc.dbcp.driverClassName}"/> <property name="url" value="${jdbc.dbcp.url}"/> <property name="username" value="${jdbc.dbcp.username}"/> <property name="password" value="${jdbc.dbcp.password}"/> <property name="initialSize" value="${jdbc.dbcp.initialSize}"/> <property name="maxTotal" value="${jdbc.dbcp.maxTotal}"/> <property name="maxIdle" value="${jdbc.dbcp.maxIdle}"/> <property name="minIdle" value="${jdbc.dbcp.minIdle}"/> <property name="defaultQueryTimeout" value="${jdbc.dbcp.defaultQueryTimeout}"/> <property name="maxWaitMillis" value="${jdbc.dbcp.maxWaitMillis}"/> <property name="connectionProperties" value="${jdbc.dbcp.connectionProperties}"/> <property name="defaultAutoCommit" value="${jdbc.dbcp.defaultAutoCommit}"/> <property name="defaultReadOnly" value="${jdbc.dbcp.defaultReadOnly}"/> <property name="defaultTransactionIsolation" value="${jdbc.dbcp.defaultTransactionIsolation}"/> <property name="lifo" value="${jdbc.dbcp.lifo}"/> <property name="poolPreparedStatements" value="${jdbc.dbcp.poolPreparedStatements}"/> <property name="maxOpenPreparedStatements" value="${jdbc.dbcp.maxOpenPreparedStatements}"/> </bean>
OK,事务管理器不用多说,非她莫属
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocations"> <value>classpath:hibernate.cfg.xml</value> </property> </bean> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="dataSource" ref="dataSource"/> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 事务管理器的具体的事务管理策略 - 示例 --> <tx:advice id="txServiceAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <!-- other methods use the default transaction settings (see below) --> <!-- 异常的冲突处理,遵循最匹配的规则。 - 就近原则 --> <tx:method name="*" /> </tx:attributes> </tx:advice> <tx:advice id="txDaoAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="*" rollback-for="java.lang.Throwable" /> </tx:attributes> </tx:advice>
这上边,一个负责Service层的声明式事务处理
一个负责DAO层的事务处理,以简化操作
2、关于Hibernate的*getCurrentSession()*方法
关于H4,网上看了一大堆垃圾信息,竟然有朵奇葩说,H4建议openSession、不建议getCurrentSession云云。真是不可理喻,误人误己。都去open了,还要Spring简化处理个毛啊。
此处在整合中,坑比较多,
但是,最重要的只有一点 -
<property name="current_session_context_class"> org.springframework.orm.hibernate4.SpringSessionContext </property>
在H3中是 - org.springframework.orm.hibernate3.SpringSessionContext
如果没有配置此项,在与Spring整合的时候,必定报错 -
可能的错误是 - org.hibernate.HibernateException: save is not valid without active transaction
有了此项配置,才有了与Spring整合的可能性,
其它的说明。比如,必须开启和提交事务才能操作、jta云云,不多说了。
交给Spring去管理就OK了。
3、关于使用*getCurrentSession()*的时候,在Spring的声明式事务处理中,提示 - org.hibernate.TransactionException: nested transactions not supported
这个错误最为坑人。又回到上面的提示 - 这个错误是最终的错误,早已南辕北辙了。
首先需要说明的是,并非是Spring的事务处理的问题,而是S4比起S3代码严谨的多。
在S3中很少会提示这个错误的,
我的项目未升级前,全部正常运行,升级之后,报的这个错误非常的奇怪,因为配置本身都是类似的。
网上的答案也是五花八门。
如果涉及到底层框架的执行的话,参考意义几乎为0。
因为事务不是我自己做的,我根本不知道到底能不能在某个时刻真正的执行,想了好久,不知所云。果断打断点,看代码。
我注意到了两点,执行目标方法前,执行了一个aspect,执行了一个advisor
代码中,事务开启之后,再次开启了,就报了这个错误。
问题涉及两点,
一是事务的传播属性为默认,
二是执行方法只有一个,但是涉及到的切面很多,再带上声明式事务的advisor。
为什么会开启两次?
去排查aspect方法,果然发现了!
有切面类手动处理了事务,去操作数据库
由于方法单一,并未考虑Spring声明式
考虑的话,事务嵌套的问题可能会更加严重。
由此,总结出一点,
在Spring的执行流程中,
默认传播属性的执行中,
session一直存在,那么,这个session获取的事务,只要有一处完成了开启,那么后期处理的时候,全部都是开启的。无需再次开启。否则就会引起事务嵌套问题而报错。
问题的关键在于分清楚,到底谁是目标方法,其它的切面以及advisor的执行时机。
当然,这只是当前情境下的一种解决方案,仅供参考。
如需要转载
请注明文章出处
https://my.oschina.net/u/3032872/blog/1648364
谢谢~
相关文章推荐
- spring@Transactional注解解决事务处理问题
- 关于Spring整合Hibernate事务问题
- 画蛇添足-记spring3 hibernate4整合时遇到问题的处理办法
- SpringMVC关于事务的处理问题(待解决)
- spring@Transactional注解解决事务处理问题
- 关于spring boot整合druid连接池在程序关闭后连接不释放问题解决
- hibernate4整合spring3事务问题
- 关于Spring 声明式事务处理时,throws exception不回滚的问题
- 实践中遇到Ibatis和spring整合事务不回滚的问题解决
- hibernate4整合spring3事务问题
- 关于SSM框架整合Spring与Mybaitis面向接口编程时,多个不同包别名设置,多个dao层包通配符表达处理问题
- 关于spring升级到4.3.12 hibernate升级到4.3 遇到的一些问题和解决方法
- 关于spring4和hibernate4整合,配置事务报“Cannot unwrap to requested type [javax.sql.DataSource]”错误的解决方法及心得
- 关于“Spring3 ”与 “Hibernate4” 整合,HibernateTemplate的使用问题。
- Spring整合hibernate关于控制事务的问题
- mybatis整合spring、springmvc时业务层无法进行事务回滚问题解决
- Maven项目中,关于Spring Boot 整合MyBatis时,Service层无法找到mapper接口的问题解决
- spring@Transactional注解解决事务处理问题
- Spring4+Hibernate4整合问题解决
- spring@Transactional注解解决事务处理问题