【Spring事务失效】DAO层未采用Spring jdbc封装

记录自己遇到的问题、解决办法、过程中查资料的收获(可能是扩展的知识,与解决问题无关,但认为有价值的)

背景

创建了两个spring事务的demo工程,分别基于xml和声明式事务,但发现都不生效,遇运行时异常不回滚。

解决过程

大部分文章讲的spring事务失效原因都比较浅显,有java基础的人不太会犯。搜索过程中也瞎尝试过设置tx:method标签属性rollback-for为java.lang.RuntimeException.class(其实不用设置,默认就是),aop:config标签属性proxy-target-class=“true”(表示使用cglib代理方式),但均未解决问题。
手头有正确代码工程,eclipse的,将其导入eclipse,一直显示xsd loading,将所有xsd由http路径改为本地路径后好了,如classpath:org\springframework\beans\factory\xml\spring-beans.xsd。工程运行ok,事务正常回滚。查看其DAO层代码,发现用的JdbcTemplate,而我的工程(采用intellij,感觉intellij方便,所以一直习惯用它)的DAO层直接注入c3p0 DataSource,并从其取得PreparedStatement执行。有点儿感觉到是不是DAO层的问题,脑海里有一个问题浮现,就是spring凭啥要帮我管理事务呢,要知道我的c3p0和spring没半点关系,虽然配置了xml事务,但看不出两者的关联。
虽然心里有这样的疑问,但也还不确定,于是各种查spring事务原理、spring事务原理threadlocal、spring事务原理aop源码。直到在一篇1文章里有提到TransactionAwareDataSourceProxy,于是查看spring javadoc2,看了相关api说明,包括JdbcTemplate,遂有思路。解决办法就是将数据源用JdbcTemplate包装,使用JdbcTemplate去做各种sql操作。
试验中发现,tx:attributes的子标签tx:method必须设置,即使是设置*也好,因为虽然事务属性的默认值如传播性、隔离性等都有,但是其是依附于被事务注解的方法的,若是tx:method没有任何方法,则事务并不会作用在任何方法上了。关于传播性,试验中发现,方法A调用方法B,A与B均被事务所标志时才涉及传播的问题,否则事务只在B中,A中在调用B后发生的异常不会造成B的回滚。

相关API

Advice:标记接口,实现可以是任何类型,例如拦截器。
Interceptor:org.aopalliance.intercept包下的接口,继承了Advice接口,该接口位于org.aopalliance.aop包下。
MethodInterceptor:org.aopalliance.intercept包下的接口,继承Interceptor。函数式接口,唯一方法Object invoke(MethodInvocation invocation)。
JoinPoint:org.aopalliance.intercept包下的接口。有三个方法:getStaticPart()、getThis()、proceed。
Invocation:org.aopalliance.intercept包下的接口,继承JoinPoint。新增了一个方法:getArguments()。
MethodInvocation:org.aopalliance.intercept包下的接口,继承Invocation。新增了一个方法:getMethod()。
TargetClass:用于得到代理的目标对象,由AOP代理对象和代理工厂(通过Advised)以及TargetSource实现。
Advisor:持有AOP增强器(作用于连接点的行为)和一个用于决定是否使用增强器的过滤器(如切点)。该接口不是为spring用户设计的,而是考虑到支持不同类型的增强器的共性。Spring AOP是基于around advice通过方法拦截,与AOP Alliance的拦截API相兼容。Advisor接口支持不同的增强器,例如before和after增强器,不需要用拦截实现。
Advised:由持有AOP代理工厂类的配置的类实现。这个配置包括拦截器和其它增强器、顾问和代理接口。任何由spring得到的AOP代理都可以类型转换为该接口以操作它的AOP增强器。包含增加、删除advice/advisor的方法、设置是否将代理保留在ThreadLocal以便通过AopContext查找和使用。
ProxyConfig:用来创建代理的配置的方便的超类,保证代理创建者有一致的属性。有些方法和Advised接口相同,如设置是否存储代理于ThreadLocal,有个特殊方法setOpaque()控制这个配置是否能被转换为Advised类型,false为能。
AdvisedSupport:继承了ProxyConfig,实现了Advised接口。AOP代理配置管理器的基类。AOP代理配置管理器不是AOP代理,但是AdvisedSupport的子类通常是AOP代理实例的创建工厂。AdvisedSupport减轻了子类管理增强器和顾问(Advisor)的负担,但并不实现代理创建方法,这些是由子类提供。AdvisedSupport是序列化的,子类不需要。AdvisedSupport被用来持有代理的快照。继承ProxyConfig类,实现Advised接口。
AopProxy:配置好的AOP代理的委托接口,考虑到实际代理对象的创建。DefaultAopProxyFactory有对JDK动态代理和CGLIB代理的开箱即用的实现。两个方法Object getProxy()与Object getProxy(ClassLoader classLoader)。
AopProxyFactory:创建AOP代理的工厂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值