乐趣区

关于后端:动力节点Spring框架学习笔记王鹤四Spring事务

四、Spring 事务 

官网下载地址

能源节点 spring 材料

视频观看地址

https://www.bilibili.com/vide…

4.1 Spring 的事务管理

事务本来是数据库中的概念,在 Dao 层。但个别状况下,须要将事务晋升到业务层,即 Service 层。这样做是为了可能应用事务的个性来治理具体的业  务。

在 Spring 中通常能够通过以下两种形式来实现对事务的治理:

(1)应用 Spring 的事务注解治理事务

(2)应用 AspectJ 的 AOP 配置管理事务

4.2 Spring 事务管理 API

Spring 的事务管理,次要用到两个事务相干的接口。

(1)事务管理器接口(重点)

事务管理器是 PlatformTransactionManager 接口对象。其次要用于实现 事务的提交、回滚,及获取事务的状态信息。

A、罕用的两个实现类

PlatformTransactionManager 接口有两个罕用的实现类:

DataSourceTransactionManager:应用 JDBC 或 MyBatis 进行数据库操作时应用。

HibernateTransactionManager:应用 Hibernate 进行长久化数据时应用。

B、Spring 的回滚形式(了解)

Spring 事务的默认回滚形式是:产生运行时异样和 error 时回滚,产生受 查 (编译) 异样时提交。不过,对于受查异样,程序员也能够手工设置其回滚形式。

C、回顾谬误与异样 (了解)

Throwable 类是 Java 语言中所有谬误或异样的超类。只有当对象是此类 (或其子类之一) 的实例时,能力通过 Java 虚拟机或者 Java 的 throw 语句抛出。

Error 是程序在运行过程中呈现的无奈解决的谬误,比方 OutOfMemoryError、ThreadDeath、NoSuchMethodError 等。当这些谬误产生时,程序是无奈解决(捕捉或抛出)的,JVM 个别会终止线程。

程序在编译和运行时呈现的另一类谬误称之为异样,它是 JVM 告诉程序员 的一种形式。通过这种形式,让程序员晓得曾经或可能呈现谬误,要求程序员对其进行解决。

异样分为运行时异样与受查异样。

运行时异样,是 RuntimeException 类或其子类,即只有在运行时才呈现 的异样。如,NullPointerException、ArrayIndexOutOfBoundsException、IllegalArgumentException 等均属于运行时异样。这些异样由 JVM 抛出,在 编译时不要求必须解决(捕捉或抛出)。但,只有代码编写足够认真,程序足  够强壮,运行时异样是能够防止的。

受查异样,也叫编译时异样,即在代码编写时要求必须捕捉或抛出的异 常,若不解决,则无奈通过编译。如 SQLException,ClassNotFoundException,IOException 等都属于受查异样。

RuntimeException 及其子类以外的异样,均属于受查异样。当然,用户   自定义的 Exception 的子类,即用户自定义的异样也属受查异样。程序员在定 义异样时,只有未明确申明定义的为 RuntimeException 的子类,那么定义的 就是受查异样。

(2)事务定义接口

事务定义接口 TransactionDefinition 中定义了事务形容相干的三类常量:事务隔离级别、事务流传行为、事务默认超时时限,及对它们的操作。

A、定义了五个事务隔离级别常量(把握)

这些常量均是以 ISOLATION_结尾。即形如 ISOLATION_XXX。

  • DEFAULT:采纳 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ;Oracle 默认为 READ_COMMITTED。
  • READ_UNCOMMITTED:读未提交。未解决任何并发问题。
  • READ_COMMITTED:读已提交。解决脏读,存在不可反复读与幻读。
  • REPEATABLE_READ:可反复读。解决脏读、不可反复读,存在幻读
  • SERIALIZABLE:串行化。不存在并发问题。

B、定义了七个事务流传行为常量(把握)

所谓事务流传行为是指,处于不同事务中的办法在互相调用时,执行期间事务的保护状况。如,A 事务中的办法 doSome()调用 B 事务中的办法 doOther(),在调用执行期间事务的保护状况,就称为事务流传行为。事务传 播行为是加在办法上的。

事务流传行为常量都是以 PROPAGATION_ 结尾,形如 PROPAGATION_XXX。

  • PROPAGATION_REQUIRED
  • PROPAGATION_REQUIRES_NEW
  • PROPAGATION_SUPPORTS
  • PROPAGATION_MANDATORY
  • PROPAGATION_NESTED
  • PROPAGATION_NEVER
  • PROPAGATION_NOT_SUPPORTED

a、PROPAGATION_REQUIRED:

指定的办法必须在事务内执行。若以后存在事务,就退出到以后事务中;若以后没有事务,则创立一个新事务。这种流传行为是最常见的抉择,也是

Spring 默认的事务流传行为。

如该流传行为加在 doOther()办法上。若 doSome()办法在调用 doOther() 办法时就是在事务内运行的,则 doOther()办法的执行也退出到该事务内执行。若 doSome()办法在调用 doOther()办法时没有在事务内执行,则 doOther()办法会创立一个事务,并在其中执行。

b、PROPAGATION_SUPPORTS

指定的办法反对以后事务,但若以后没有事务,也能够以非事务形式执行。

c、PROPAGATION_REQUIRES_NEW

总是新建一个事务,若以后存在事务,就将以后事务挂起,直到新事务执行结束。

C、定义了默认事务超时时限

常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,sql 语句的执 行时长。

留神,事务的超时时限起作用的条件比拟多,且超时的工夫计算点较复 杂。所以,该值个别就应用默认值即可。

4.3   程序举例环境搭建

举例:购买商品 trans_sale 我的项目

本例要实现购买商品,模仿用户下订单,向订单表增加销售记录,从商品表减 少库存。

实现步骤:

Step0:创立数据库表
创立两个数据库表 sale , goods

sale 销售表

goods 商品表

goods 表数据

Step1:   maven 依赖 pom.xml

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <version>5.1.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>

插件

<build>
<resources>
<resource>
<directory>src/main/java</directory><!-- 所在的目录 - ->
<includes><!-- 包含目录下的.properties,.xml 文件都会
扫描到 -->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId> <version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

Step2:创立实体类

创立实体类 Sale 与 Goods

Step3:定义 dao 接口

定义两个 dao 的接口 SaleDao , GoodsDao

 

Step4:定义 dao 接口对应的 sql 映射文件

SaleDao.xml

GoodsDao.xml

Step5:定义异样类

定义 service 层可能会抛出的异样类 NotEnoughException

Step6:定义 Service 接口

定义 Service 接口 BuyGoodsService

Step7:定义 service 的实现类

定义 service 层接口的实现类 BuyGoodsServiceImpl

1)  类定义

2)  Dao 属性

 

3)  Buy 办法

Step8:批改 Spring 配置文件内容

申明 Mybatis 对象

申明业务层对象

 

Step9:定义测试类

定义测试类 MyTest。当初就能够在无事务代理的状况下运行了。

4.4   应用 Spring 的事务注解治理事务(把握)

通过 @Transactional 注解形式,可将事务织入到相应 public 办法中,实 现事务管理。

@Transactional 的所有可选属性如下所示:

  • propagation:用于设置事务流传属性。该属性类型为 Propagation 枚举,默认值为 Propagation.REQUIRED。
  • isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为 Isolation.DEFAULT。
  • readOnly:用于设置该办法对数据库的操作是否是只读的。该属性为 boolean,默认值为 false。
  • timeout:用于设置本操作与数据库连贯的超时时限。单位为秒,类型为 int,默认值为 -1,即没有时限。
  • rollbackFor:指定须要回滚的异样类。类型为 Class[],默认值为空数组。当然,若只有一个异样类时,能够不应用数组。
  • rollbackForClassName:指定须要回滚的异样类类名。类型为 String[],默认值为空数组。当然,若只有一个异样类时,能够不应用数组。
  • noRollbackFor:指定不须要回滚的异样类。类型为 Class[],默认值为空数组。当然,若只有一个异样类时,能够不应用数组。
  • noRollbackForClassName:指定不须要回滚的异样类类名。类型为 String[],默认值为空数组。当然,若只有一个异样类时,能够不应用数组。

须要留神的是,@Transactional 若用在办法上,只能用于 public 办法上。对于其余非 public 办法,如果加上了注解 @Transactional,尽管 Spring 不会报错,但不会将指定事务织入到该办法中。因为 Spring 会疏忽掉所有非 public 办法上的 @Transaction 注解。

若 @Transaction 注解在类上,则示意该类上所有的办法均将在执行时织入 事务。

实现注解的事务步骤:

复制 trans_sale 我的项目,新我的项目 trans_sale_annotation

1.  申明事务管理器

2.  开启注解驱动

transaction-manager:事务管理器 bean 的 id 

3.  业务层 public 办法退出事务属性

4.5   应用 AspectJ 的 AOP 配置管理事务(把握)

应用 XML 配置事务代理的形式的有余是,每个指标类都须要配置事务代 理。当指标类较多,配置文件会变得十分臃肿。

应用 XML 配置参谋形式能够主动为每个合乎切入点表达式的类生成事务代 理。其用法很简略,只需将后面代码中对于事务代理的配置删除,再替换为如  下内容即可。

Step1:复制我的项目

复制 trans_sale 我的项目,并重命名为 trans_sal_aspectj。在此基础上批改。

Step2:maven 依赖 pom.xml

新退出 aspectj 的依赖坐标

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aspects</artifactId>

<version>5.2.5.RELEASE</version>

</dependency>

Step3:在容器中增加事务管理器

Step4:配置事务告诉

为事务告诉设置相干属性。用于指定要将事务以什么形式织入给哪些办法。

例如,利用到 buy 办法上的事务要求是必须的,且当 buy 办法产生异样后要回滚业务。

Step5:配置增强器

指定将配置好的事务告诉,织入给谁。

Step6:批改测试类

测试类中要从容器中获取的是指标对象。

退出移动版