Spring、Springboot入门之事务处理

1.什么是事物

通俗讲事物就是一组原子操作单元,组内的操作要么全部执行成功,要么全部失败。

事务有四个特性:ACID
1)原子性(Atomicity)     

        事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。


2)一致性(Consistency)

        一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。


3)隔离性(Isolation)  

        可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。


4)持久性(Durability)  

        一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。

2.Spring事物

Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器

1)编程式事务:

编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。

2)声明式事务:

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务          逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

3.Springboot事物

Springboot默认使用声明事物,本文主要讲述springboot声明式事务的注解使用方式。

1)开启事物支持,在启动类上加上@EnableTransactionManagement注解开启事物支持(非必须,视具体情况而定,加上没毛病) 

2)开启事物,在需要开启事物的类上或者方法上加上@Transactional 注解开启事物(在public的方法上使用@Transactional 注解开启事物,其他类型的方法加上@Transactional编译执行不报错但是事物失效)

@Transactional 开启事物注解,可以用在类或者方法上,在类上使用则类中所有方法采用相同的事物配置(不建议使用因为实际开发中查询的比例远大于插入更新等操作),在方法上配置时,方法上的配置信息会覆盖类上(优先级高于类上的配置)的配置(建议在方法上使用,每个事物需要配置的超时时间,传播属性等配置可能不同), @上源码

package org.springframework.transaction.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED; // 事物的传播属性 默认支持当前事务,如果当前没有事务,就新建一个事务。

    Isolation isolation() default Isolation.DEFAULT;        // 事物的隔离级别 默认数据库设置隔离级别

    int timeout() default -1;                               // 超时时间 默认-1 不超时

    boolean readOnly() default false;                       // 只读标识 默认false标识非只读 需要开启事物 如果是select查询操作则可以设置为true无需开启事物

    Class<? extends Throwable>[] rollbackFor() default {};  // 指定回滚异常类型,默认回滚运行时异常和Error,如检查类型的异常不会回滚事物(若果想回滚所有异常可以如下设置rollbackFor = {Exception.class}),catch处理后无重新抛出的异常不会回滚

    String[] rollbackForClassName() default {};             // 指定回滚异常类

    Class<? extends Throwable>[] noRollbackFor() default {};// 排除回滚异常类型

    String[] noRollbackForClassName() default {};           // 排除回滚异常类
}
Propagation 七种事物的传播行为
package org.springframework.transaction.annotation;

public enum Propagation {
    REQUIRED(0),      // 必修的   支持当前事务,如果当前没有事务,就新建一个事务。[默认] 
    SUPPORTS(1),      // 支持     支持当前事务,如果当前没有事务,就以非事务方式执行。
    MANDATORY(2),     // 强制性的 支持当前事务,如果当前没有事务,就抛出异常。 
    REQUIRES_NEW(3),  // 需要新的 新建事务,如果当前存在事务,把当前事务挂起。
    NOT_SUPPORTED(4), // 不支持   以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
    NEVER(5),         // 从不     以非事务方式执行,如果当前存在事务,则抛出异常。
    NESTED(6);        // 嵌套的   如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

    private final int value;

    private Propagation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

Isolation 4中隔离级别
public enum Isolation {
    DEFAULT(-1),         // 默认数据库设置隔离级别 oracle【READ_COMMITTED】 mysql【REPEATABLE_READ】
    READ_UNCOMMITTED(1), // 读未提交  =》 存在脏读,不可重复读(并发修改读取问题),幻读问题(增删读取问题)
    READ_COMMITTED(2),   // 读已提交  =》 存在不可重复读,幻读问题
    REPEATABLE_READ(4),  // 可重复读  =》 存在幻读问题
    SERIALIZABLE(8);     // 串行化    =》 不存在上述所有问题,但是数据库并发效率最低

    private final int value;

    private Isolation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

4.@Transactional使用注意事项

1)默认传播属性REQUIRED有加入没有新建,但SUPPORTS(有可能),NOT_SUPPORTED(一定),NEVER(一定)不产生事务回滚异常。

2)默认回滚异常运行时异常、Error,不回滚受检异常(例如IOException,可以通过指定@Transactional(rollbackFor = Exception.class)的方式进行全异常捕获),如需自定义控制回滚异常可以通过设置rollbackFor实现。

3)非Transactional标记方法调用@Transactional标记方法时,被@Transactional标记方法的事务失效(事务是由代理对象控制的,内部对象无事务逻辑可以通过AopContext.currentProxy()获取代理对象)。

4)必须使用在public方法上,不能用在private,final,static方法上,否则不会生效。

@浅见 @如有疏漏请大家帮忙补充完善 @开发一家人 完善中

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值