本文主要是介绍ssm 之事务管理出现错误,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
JDBC Connection will not be managed by Spring
项目采用的是分布式架构,分别有controller,service,solr三个服务器,之间通过dubbo进行调用,经过测试发现事务配置完以后不能通过spring进行管理,其中两条insert和一条update语句都执行完毕,异常并没有使得事务进行回滚,通过调取debug日志发现“JDBC Connection will not be managed by Spring”,即spring不能管理jdbc的连接。
然后怀疑是Spring事务的传播方式出现问题,改了事务的传播方式,具体如下所示:
Spring事务的传播行为
在service类前加上@Transactional,声明这个service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。
Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked
如果遇到checked意外就不回滚。
如何改变默认规则:
1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)
2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
3 不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
在整个方法运行前就不会开启事务
还可以加上:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),这样就做成一个只读事务,可以提高效率。
各种属性的意义:
REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。
NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。
REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。
MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。
SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。
NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执行。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
但是!事务仍然没有起到作用!
而后有查询了一些资料,因为采用的springmvc+spring+mybatis框架,springmvc的配置文件和spring的配置文件中都有包扫描
<context:component-scan base-package="com.xxx.xxx.service" />,而又因为service工程中采用的是dubbo的调用方式,没有springmvc包扫描的必要,所以讲包扫描去掉,然后一切正常,测试通过了!
问题反思:由于采用的是SpringMVC、 MyBatis,故统一采用了标注来声明Service、Controller
服务器启动时的加载配置文件的顺序为web.xml----applicationContext.xml----spring-mvc.xml(SpringMVC的配置文件),由于applicationContext.xml配置文件中Controller会先进行扫描装配,而Controller在这个项目中没有配置,所以必须将springmvc中的<context:component-scan base-package="com.xxx.xxx.service" />去除,不然注解扫描不到。
这篇关于ssm 之事务管理出现错误的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!