四、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:批改测试类

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