Spring声明事务

1、回顾事务

1.1事务四大特征(ACID)

  • 原子性(Atomicity):每一个事务都是一个整体,不可再拆分,事务中所有的 SQL 语句要么都执行成功, 要么都失败。

  • 一致性(Consistency):事务在执行前数据库的状态与执行后数据库的状态保持一致。如:转账前2个人的总金额是2000,转账后2个人总金额也是 2000。

  • 隔离性(Isolation):事务与事务之间不应该相互影响,执行时保持隔离的状态。

    • 多个业务可能操纵同一个资源,防止数据损坏

  • 持久性(Durability):一旦事务执行成功,对数据库的修改是持久的。就算关机,也是保存下来的。

2、spring中的事务配置

2.1声明式事务的两种配置方式

1.配置xml文件

配置声明事事务(开启事务)

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <!--<constructor-arg ref="dataSource" />-->
  <constructor-arg name="dataSource" ref="dataSource" />
</bean>

结合aop实现事务的织入

<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!--给哪些事务配置通知-->
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="select" read-only="true"/>
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>  
​

意思是这个事物advice的管理者为transactionManager,你从配置文件中应该能够找到一个ID为transactionManager的bean,而这个建议中规定了save方法的传输方式为required,也就是说没有sessionfactory的时候会自动建立,有的时候就不会建立了。 当然了这只是规定了一个advice,你还需要指定一个aop:pointcut去引用他,例如

<!--配置事务切入-->
<aop:config>
    <aop:pointcut id="txPointCut" expression="execution(* com.hyqj.dy.mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"
</aop:config>

这样这个advice就被联系到了bussinessService这个pointcut上了

在Transactional注解中配置参数的说明

  • propagation:事务传播行为 即表现为,当有事务的方法调用没有执行事务的方法,具体应该如何去处理。

  • isolation: 事务隔离级别

  • timeout:超时时间,事务需要在一定的时间内进行提交,如果不提交进行回滚 默认值是-1 (不超时) 设置时间以秒为单位

  • readOnly:是否只读 默认值是false,如果是true 则表示只能查询,不能修改添加删除。

  • rollbackFor:回滚,设置出现哪些异常进行事务回滚

  • noRollbackFor:不回滚,设置出现哪些异常不进行事务回滚

propagation(事务的传播属性)的七大属性

  • REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。(Sring默认的)

  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。supports

  • MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。mandatory

  • REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

  • NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。nested

2.注解配置

也需要先配置事务声明。 

只需在需要spring来帮忙管理事务的方法上加上@Transaction注解就可以了,注解的方式相对来说更简洁一些,都需要开发者自己去进行配置

@Transactional

@Transactional可以作用在接口、类、类方法;

  • 作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息,会导致事务控制的粒度太大,注解参数无法根据每个类方法的实际需求设置;因此,一般@Transactional注解都会直接添加的需要的方法上;

  • 作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息;

  • 作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效;

@Transactional默认只能回滚RuntimeException和RuntimeException下面的子类抛出的异常,不能回滚Exception异常;如果需要支持回滚Exception异常,需要显示的指明,如@Transactional(rollbackFor = Exception.class);

2.2、编程式事务

编程式事务主要有两种用法:通过事务管理器PlatformTransactionManager控制事务和通过事务模板TransactionTemplate控制事务;常用的是TransactionTemplate,如下:

 private DataSourceTransactionManager transactionManager;
   
    // 同类方法调用 使用编程式事务
    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    transactionTemplate.execute(transactionStatus -> {
        queryData();
        insertData();
        return Boolean.TRUE;
​
    });
public class UserService {
  private final PlatformTransactionManager transactionManager;
  public UserService(PlatformTransactionManager transactionManager) {
    this.transactionManager = transactionManager;
  }
  public void createUser() {
    TransactionStatus txStatus =
        transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
      userMapper.insertUser(user);
    } catch (Exception e) {
      transactionManager.rollback(txStatus);
      throw e;
    }
    transactionManager.commit(txStatus);
  }
}

TransactionStatus表示一个事物的状态。接口提供了控制事务执行和查询事务状态的方法。比如当前调用栈中之前已经存在了一个事物,那么就是通过该接口来判断的,TransactionStatus接口可以让事务管理器控制事务的执行,

如果项目中有些业务逻辑比较简单,而且不经常变动,建议使用@Transactional注解开启事务,因为它更简单,开发效率更高,但是千万要小心事务失效的问题;而使用编程式事务有时可以帮我们解决@Transactional注解声明式事务解决不了的问题,如同类调用;二者可以配合使用;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值