spring事务管理的两种方式注意细节

1 篇文章 0 订阅
1 篇文章 0 订阅

在这里我们只是说spring和myBatis的事务使用方式

目前事务分为声明式事务和编程事务,编程式事务就不做详细介绍了

今天说一下声明式事务,常用的声明式事务方式分为:aspectJ和注解

 

首先说一下aspectJ的配置说明

<!-- 定义事务 -->

<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <property name="dataSource" ref="dataSourceWeb"/>

</bean>

<!-- 拦截器方式配置事物-->

<tx:adviceid="transactionAdvice"transaction-manager="transactionManager">

<tx:attributes>

             <tx:methodname="*" propagation="REQUIRED" read-only="false"

rollback-for="Throwable" />

</tx:attributes>

</tx:advice>

<aop:config>

        <aop:pointcut id="transactionPointcut"

expression="execution(* com.eventown.btravel.service..*.*(..))"/>

<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice"/>

</aop:config>                    

 

说一下上面的代码,首先我们需要一个事务管理器来对数据源做事务的控制,然后我们需要配置事务建议和事务的传播特性。什么叫传播特性,这里有必要详细解释一下:

事务的传播特性就是指多个事务方法调用时候,事务如何在这些方法间进行传递

Spring提供了7种事务的传播特性分别是:

特性名称

特性描述

PROPAGATION_REQUIRED

如果存在一个事务,则支持当前事务。如果没有事务则开启,通常做为默认的特性

PROPAGATION_SUPPORTS

如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

PROPAGATION_MANDATORY

 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常

PROPAGATION_REQUIRES_NEW

总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起

PROPAGATION_NOT_SUPPORTED

总是非事务地执行,并挂起任何存在的事务。

PROPAGATION_NEVER

 总是非事务地执行,如果存在一个活动事务,则抛出异常

PROPAGATION_NESTED

如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动事务

        

                  

在这里我们可以配置多种不同方法的事务传播行为

<tx:method name="*"propagation="REQUIRED" read-only="false"

rollback-for="Throwable" />

说明一下这里的参数

参数名称

注释

name

匹配当前方法名称的所有方法,可以使用*通配符,save*,代表以save开头的所有方法

propagation

指示当前方法所使用的事务传播机制

isolation

事务的隔离级别,一般使用默认值就行(DEFAULT)

read-only

事务是否只读, 表示此方法只能用于查询

rollback-for

触发回滚的异常,包含当前类以及子类(可以不配置)

no-rollback-for

不触发回滚的异常类(可以不配置)

 

之后我们需要配置aop拦截设置

在aop:config中我们需要指定我们的切割点和对应事务配置的建议(advice)

<aop:pointcut id="transactionPointcut"

expression="execution(。。。。)"/>

这个切割点我们需要指代一个使用aspectJ的表达式来指定某些返回值的某些包下的某些包的某些方法具体指定到方法级为止

execution(* com.ning.service..*.*(..))

 

第一个*号是指返回值类型,当然在返回值类型之前我们也可以指代此方法是public类型的

 

后面跟着是我们的包名,以上为例,包名后面如果跟着两个点,则代表service包和子包的所有类全都在事务的管理范围之中,当然如果只有一个点只表示service包下的所有类,子包下的类不在事务管理范围

 

后面的第二个*代表的是类名,代表了所有的类

 

后面*(..)代表了类下的所有方法,里面的两个点代表了所有的参数

 

总体来说完整的写法就是

 

execution(* com.ning.service..*.*(..)) 

代表的意思是:com.ning.service包和子包下的所有方法都是切割点

这种写法也是基本所有项目都会使用的,如果有特殊要求的还是建议多看看aspectJ的表达式,来写出精确的表达式

 

接下来就是需要将我们写的切割点和我们的事务建议(advice)进行组合

aop:advisor

这个标签有两个属性pointcut-ref和advice-ref

pointcut-ref指的是切割点

advice-ref是事务的建议(advice)

到此位置就完成了事务的第一种配置

 

 

下面我们来说一下关于注解的配置

注解的配置需要我们在配置文件中配置的内容就比较少

 

<bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <!-- 配置TransactionManager -->

       <constructor-arg name="dataSource"ref="dataSourceWeb"/>

   </bean>

<!-- 开启事务注解 --> 

<tx:annotation-driven transaction-manager="txManager"/>

 

这里首先为数据源定义一个事务管理器,使用这个事务管理器来管理我们的注解事务

之后我们就对我们的service类添加注解来提供事务

 

 

 

属性

描述

value

可选的限定描述符,指定使用的事务管理器

propagation

可选的事务传播行为设置

isolation

可选的事务隔离级别设置

readOnly

读写或只读事务,默认读写

timeout

事务超时时间设置

rollbackFor

导致事务回滚的异常类数组

rollbackForClassName

导致事务回滚的异常类名字数组

noRollbackFor

不会导致事务回滚的异常类数组

noRollbackForClassName

不会导致事务回滚的异常类名字数组

 

@Transactional

public class UserService{
        

         @Transactional

         publicvoid save(){}

 

         publiUser queryAndUpdate(){

                   //TODO

                   update();

         }

        

         @Transactional

         publicvoid update(){}
}

 

@Transactional 可以写在类名上,也可以只写在方法上,

 

但是需要注意的是,当同一个类中,如果该类没有添加注解,仅仅只是在部分方法上添加了事务注解,那么一个没有事务的方法调用了一个有事务的方法,那么该事务不会生效

这是因为注解方式的实现方式导致的,所以我们尽量对需要有事务的方法都放在一个类中,没有事务的方法放在另外一个类中,避免这种问题的出现

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值