Spring事务相关的整理

Spring事务

一、概述

1、传播机制(Propagation)

A业务方法调用B业务方法,如果A……,则B……

  • REQUIRED:默认的传播特性,如果当前没有事务,则新建一个事务,如果当前存在事务,则加入这个事务。(无则新建,有则加入)

  • SUPPORTS:当前存在事务,则加入当前事务,如果当前没有事务,则以非事务的方式执行(有则加入,无则无为)

  • MANDATORY:当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常(有则加入,无则警告)

  • REQUIRED_ NEW:创建一个新事务,如果存在当前事务,则挂起该事务(无则新建,有则挂起)

  • NESTED:如果当前事务存在,则在嵌套事务中执行,否则和REQUIRED的操作一样(新建一个事务)。(无则新建,有则嵌套;需要注意的是,NESTED仅支持JDBC,不支持JPA或者Hibernate)

  • NOT_ SUPPORTED:以非事务方式执行,如果存在当前事务,则挂起当前事务*(有则挂起,无则无为)

  • NEVER:不使用事务,如果当前事务存在,则抛出异常*(有则警告,无则无为)

    • NESTED和REQUIRED_ NEW的区别:

      ​ REQUIRED_ NEW是新建一个事务并且新开始的这个事务与原有事务无关, 而NESTED则是当前存在事务时会
      开启一个嵌套事务,在NESTED情况下,父事务回滚时,子事务也会回滚,而REQUIRED_ NEW情况下,原有事务
      回滚,不会影响新开启的事务

    • NESTED和REQUIRED的区别:

      ​ REQUIRED情况下,调用方存在事务时,则被调用方和调用方使用同一个事务,那么被调用方出现异常时,由
      于共用一个事务,所以无论是否catch异常,事务都会回滚,而在NESTED情况下,被调用方发生异常时,调用方
      可以catch其异常,这样只有子事务回滚,父事务不会回滚。

  • 超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置。

  • 是否只读:查询时设为只读。

2、隔离级别(Isolation)

  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIZALZABLE
  • DEFAULT

在进行配置的时候,如果数据库和Spring代码中的隔离级别不同,那么以Spring的配置为主。

3、实现原理

​ 在使用Spring框架的时候,可以有两种事务的实现方式:

  • 编程式事务:由用户自己通过代码来控制事务的处理逻辑,
  • 声明式事务: 通过@Transactional注解来实现。

​ 其实事务的操作本应由数据库来进行控制,但是为了方便用户进行业务逻辑的操作, Spring对事务功能进行了扩展实现,一般很少会用编程式事务,更多的是通过添加@Transactional注解来进行实现。
当添加@Transactional注解之后数据库事务的自动功能就会关闭,由Spring框架来帮助进行控制。

​ 其实事务操作是AOP的一个核心体现,当一个方法添加@Transactional注解之后,Spring会基于这个类生成一个代理对象,会将这个代理对象作为bean,当使用这个代理对象的方法的时候,如果有事务处理,那么会先把事务的自动提交给关系,然后去执行具体的业务逻辑,如果执行逻辑没有出现异常,那么代理逻辑就会直接提交,如果出现任何异常情况,那么直接进行回滚操作,当然用户可以控制对哪些异常进行回滚操作。

4、Spring事务什么时候会失效?

  • 1、bean对象没有被Spring容器管理
  • 2、方法的访问修饰符不是public
  • 3、自身调用问题
  • 4、数据源没有配置事务管理器
  • 5、数据库不支持事务
  • 6、异常被捕获
  • 7、异常类型错误或者配置错误
二、编程式事务
相关对象
※1、PlatformTransactionManager

Spring的事务管理器,其中提供了常用的操作事务的方法。需要设置事务管理器。

方法说明
TransactionStatus getTransaction (TransactionDefination defination)获取事务的状态信息
void commit (TransactionStatus status)提交事务
void rollback (TransactionStatus status)回滚事务
  • 注意:PlatformTransactionManager是接口类型,不同的Dao层技术则有不同的实现类,例如:
    • Dao层技术是JDBC或Mybatis 时: org. springframework. jdbc . datasource . DataSourceTransactonManager
    • Dao层技术是Hibernate时: org . springframework . orm. hibernate5. HibernateTransactionManager
※2、TransactionDefinition

事务的定义信息对象,其中有如下方法:

方法说明
int getISolationLevel ()获得事务的隔离级别
int getPropogationBehavior ()获得事务的传播行为
int getTimeout ()获得超时时间
boolean isReadonly()是否只读

需要设置事务的隔离级别、传播行为、超时时间、是否只读。

※3、TransactionStatus

接口提供的是事务具体的运行状态,方法介绍如下。

方法说明
boolean hasSavepoint ()是否存储回滚点
boolean isCompleted ()事务是否完成
boolean i sNewTransaction ()是否是新事务
boolean isRollbac konly ()事务是否回滚
三、声明式事务

Spring的声明式事务顾名思义就是采用声明的方式来处理事务。

声明是指在配置文件中声明,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。

  • 声明式事务处理的作用
    • 事务管理不侵入开发的组件。 具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可
    • 在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便
    • 注意: Spring 声明式事务控制底层就是AOP。
(1)XML形式

1、导入相关依赖

2、导入tx的xsd约束

3、配置

	<context:property-placeholder location="classpath:jdbcConfig.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
	
	<!--配置事务管理器-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
	<!--配置事务通知-->
	<!--事务管理器ID为transactionManager时,可省略-->
    <tx:advice id="txAdvice">
        <tx:attributes>
            <!--事务属性的配置-->
            <tx:method name="transfer*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="10"/>
			<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" timeout="5"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
	<!--配置织入关系-->
    <aop:config>
        <!--由于Spring已经对事务通知封装完成,使用aop:advisor即可-->
        <!--对业务层下的所有类的所有任意参数类型及任意返回值类型的方法(切点)进行增强-->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.ming.service.impl.*.*(..))"/>
    </aop:config>

    <context:component-scan base-package="com.ming"/>
(2)注解形式
  • 1、导入相关依赖

  • 2、导入tx的xsd约束

  • 3、在需要事务控制的方法上添加@Transactional注解(也可以在类上添加,表示该类中的所有方法遵循该注解的配置进行事务)

    @Transactional(
        isolation = Isolation.REPEATABLE_READ,
        propagation = Propagation.REQUIRED,
        timeout = 10,
        rollbackFor = {RuntimeException.class,Error.class}
    )
    public class AccountServiceImpl implements AccountService {
    }
    
  • 4、开启事务的注解驱动

    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--事务管理器ID为transactionManager时,可省略-->
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值