乐趣区

关于java:十二Spring从入门到入土Spring事务

Spring 事务

事务是逻辑上的一组操作,要么都执行,要么都不执行

事务的个性(ACID)

  • 原子性
  • 一致性
  • 隔离性
  • 持久性

Spring 治理事务的形式有几种

程序是否反对事务是取决于数据库是否反对事务

MySQL 是如何保障原子性的:

复原机制是依赖回滚日志实现的

  • 编程式事务,在代码中硬编码(不举荐应用)
  • 申明式事务,在配置文件中配置(举荐应用),代码侵入性小,通过 AOP 实现
    • 基于 XML 的申明式事务
    • 基于注解的申明式事务

Spring 事务管理接口介绍

Spring 中事务管理相干的最重要的三个接口如下

  • PlatformTransactionManager:(平台)事务管理器,Spring 事务策略的外围(下层管理者)
  • TransactionDefinition:事务定义信息(事务隔离级别、流传行为、超时、只读、回滚规定)
  • TransactionStatus:事务运行状态

PlatformTransactionManager:事务管理接口

Spring 并不间接治理事务,而是提供了多种事务管理器。spring 通过该事务管理接口为多个平台提供了对应的事务管理器,具体的实现就是各个平台本人的事件了。

该接口次要是将事务管理行为形象进去,而后不同的平台去实现它,能够保障提供给内部的行为不变,不便咱们扩大。

TransactionDefinition:事务属性

该类定义了一些根本的事务属性。

  • 事务属性包含了五个方面
    • 隔离级别
    • 流传行为
    • 回滚规定
    • 是否只读
    • 事务超时

TransactionStatus:事务状态

该接口用来记录事务的状态,该接口定义了一组办法,用来获取或判断事务的相应状态信息。

public interface TransactionStatus{boolean isNewTransaction(); // 是否是新的事务
    boolean hasSavepoint(); // 是否有复原点
    void setRollbackOnly();  // 设置为只回滚
    boolean isRollbackOnly(); // 是否为只回滚
    boolean isCompleted; // 是否已实现
}

事务属性详解

Spring 事务流传行为(枚举类:Propagation)

事务流传行为是为了解决业务层之间相互调用的事务问题。

当事务办法被另一个事务办法调用时,必须制订事务应该如何流传。例如:办法可能持续在现有的事务中运行,也可能开启一个新事务,并在本人的事务中运行。

事务流传行为类型 阐明 是否反对以后事务
REQUIRED 如果以后存在事务,则退出该事务;如果以后没有事务,则创立一个新的事务。(默认状况)
SUPPORTS 如果以后存在事务,则退出该事务;如果以后没有事务,则以非事务的形式持续运行。
MANDATORY 如果以后存在事务,则退出该事务;如果以后没有事务,则抛出异样。(mandatory:强制性)
REQUIRES_NEW 创立一个新的事务,如果以后存在事务,则把以后事务挂起。
NOT_SUPPORTED** 以非事务形式运行,如果以后存在事务,则把以后事务挂起。
NEVER 以非事务形式运行,如果以后存在事务,则抛出异样。
NESTED 如果以后存在事务,则创立一个事务作为以后事务的嵌套事务来运行;如果以后没有事务,则该取值等价于 REQUIRED。

Spring 事务中的隔离级别(枚举类:Isolation)

TransactionDefinition 接口中定义了五个示意隔离级别的常量。

  • ISOLATION_DEFAULT: 后端数据库默认的隔离级别,Mysql 默认采纳的 REPEATABLE_READ 隔离级别 Oracle 默认采纳的 READ_COMMITTED 隔离级别.
  • ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,容许读取尚未提交的数据变更, 可能会导致脏读、幻读或不可反复读
  • ISOLATION_READ_COMMITTED: 容许读取并发事务曾经提交的数据, 能够阻止脏读,然而幻读或不可反复读仍有可能产生
  • ISOLATION_REPEATABLE_READ: 对同一字段的屡次读取后果都是统一的,除非数据是被自身事务本人所批改, 能够阻止脏读和不可反复读,但幻读仍有可能产生。
  • ISOLATION_SERIALIZABLE: 最高的隔离级别,齐全遵从 ACID 的隔离级别。所有的事务顺次一一执行,这样事务之间就齐全不可能产生烦扰,也就是说, 该级别能够避免脏读、不可反复读以及幻读 。然而这将重大影响程序的性能。通常状况下也不会用到该级别。

事务超时属性

所谓事务超时,就是指一个事务所容许执行的最长工夫,如果超过该工夫限度但事务还没有实现,则主动回滚事务。在 TransactionDefinition 中以 int 的值来示意超时工夫,其单位是秒,默认值是 -1

事务只读属性

对于只有读取数据查问的事务,能够指定事务类型为 readonly,即只读属性。只读事务不波及数据的批改,数据库会提供一些优化伎俩,适宜用在有多条数据库查问操作的办法中。

MySQL 默认对每一个新建设的连贯都启用了 autocommit 模式,在该模式下,每一个发送到 MySQL 服务器的 sql 语句都会在一个独自的事务中解决,执行完结后会主动提交事务,并开启一个新事务。

如果不加 Transaction,每条 sql 会开启一个独自的事务,两头被其余事务改了数据,都会实时读取到最新值。

如果你一次执行多条查问语句,例如统计查问,报表查问,在这种场景下,多条查问 SQL 必须保障整体的读一致性,否则,在前条 SQL 查问之后,后条 SQL 查问之前,数据被其余用户扭转,则该次整体的统计查问将会呈现读数据不统一的状态,此时,应该启用事务反对

事务回滚规定

这些规定定义了那些异样会导致事务回滚而那些不会。默认状况下,事务只有遇到了运行时异样(RuntimeException 的子类)时才会回滚,Error 也会导致事务回滚,然而在遇到查看型(Checked)异样时不会回滚。

如果要定义你回滚的异样类型能够这样

@Transactional(rollbackFor = MyException.class)

@Transaction 注解

作用范畴

  • 办法:举荐将注解应用在办法上,不过须要留神的是,该注解只能利用到 public 办法上,否则不失效
  • 类:如果定义在类上,阐明对该类中的所有 public 办法有无效
  • 接口:不举荐在接口上应用

罕用配置参数

@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 TransactionDefinition.TIMEOUT_DEFAULT;

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};}

@Transactional 的罕用配置参数总结

属性名 阐明
propagation 事务的传播方式,默认 REQUIRED
isolation 事务的隔离级别,默认 DEFAULT
timeout 事务超时工夫,默认 -1(不会超时)。如果超过工夫限度没有实现,则主动回滚
readOnly 指定事务是否只读,默认为 false
rollbackFor 用于指定可能触发事务回滚的异样类型,并且能够指定多个异样类型

@Transaction 事务注解原理

@Transaction 的工作机制是基于 AOP 实现的,AOP 有事应用动静代理实现的。如果指标对象实现了接口,默认状况下采纳 JDK 的动静代理,如果对象没有实现接口,会应用 Cglib 来做动静代理

createAopProxy() 办法决定了应用 JDK 还是 Cglib 来做动静代理

如果一个类或者一个类中的 public 办法上被标注 @Transaction 注解的话,Spring 容器会在启动的时候为其创立一个代理类,在调用被 @Transaction 注解的 public 办法的时候,理论调用的是 TransactionInterceptor 类中的 invoke 办法。这个办法的作用就是在指标办法之前开启事务,办法执行过程中如果遇到异样的时候回滚事务,办法调用实现后提交事务。

注解生效状况

利用在非 public 润饰的办法上

Spring AOP 自调用问题

若同一类中的其余没有 @Transaction 注解的办法外部调用有 @Transaction 注解的办法,有 @Transaction 注解的办法的事务会生效。

这是因为 Spring AOP 代理的起因造成的,因为只有 @Transaction 注解的办法在类以外被调用的时候,Spring 事务管理才失效。

解决办法就是防止同一类中自调用或者应用 AspectJ 取代 Spring AOP 代理。

propagation 属性设置谬误

rollbackFor 属性设置谬误

try/catch 中没有抛出异样导致生效

数据库不反对事务

最初

  • 如果感觉看完有播种,心愿能给我点个赞,这将会是我更新的最大能源,感激各位的反对
  • 欢送各位关注我的公众号【java 冢狐】,专一于 java 和计算机基础知识,保障让你看完有所播种,不信你打我
  • 如果看完有不同的意见或者倡议,欢送多多评论一起交换。感激各位的反对以及厚爱。

——我是冢狐,和你一样酷爱编程。

欢送关注公众号“Java 冢狐”,获取最新消息

退出移动版