Spring事务控制

简介: 本文详细介绍Sping的两种事务控制方式:xml和注解

1、什么是事务控制

Spring 提供了强大的事务管理支持,可以帮助你在应用程序中管理数据库操作的事务。事务是一组数据库操作,要么全部成功执行,要么全部失败回滚,以保持数据的一致性和完整性。Spring 的事务管理可以通过编程式或声明式的方式来实现。

以下是 Spring 事务控制的一些关键概念和介绍:

  1. 事务管理器(Transaction Manager): 事务管理器是 Spring 框架用来管理事务的核心组件。它负责启动、提交和回滚事务,以确保一组操作的原子性和一致性。
  2. 编程式事务管理: 在编程式事务管理中,开发人员手动编写代码来控制事务的开始、提交和回滚。这种方式灵活,但可能导致代码与事务管理的耦合。
  3. 声明式事务管理: 声明式事务管理通过使用 AOP 技术将事务逻辑从业务逻辑中分离出来,以声明的方式来定义事务的行为。通常使用基于注解或 XML 配置来实现。
  4. 事务传播行为(Propagation): 事务传播行为定义了一个方法调用在一个已经存在的事务中执行时,应该如何处理事务。例如,REQUIRED 表示方法必须在事务中执行,REQUIRES_NEW 表示方法将创建一个新事务。
  5. 事务隔离级别(Isolation Level): 事务隔离级别定义了多个事务之间的隔离程度,以防止并发访问数据库时的数据不一致问题。常见的隔离级别有 READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE。
  6. 事务超时(Timeout): 事务超时设置了一个时间限制,在指定时间内事务必须完成,否则将被自动回滚。
  7. 只读事务(Read-Only Transactions): 只读事务标记了在事务期间不会修改数据的操作,这可以优化性能。
  8. 回滚规则(Rollback Rules): 回滚规则定义了在哪些异常发生时事务应该回滚。
  9. 声明式事务管理的配置: 通过 Spring 的 XML 配置或注解,你可以定义事务管理器、事务属性、切点等,从而实现声明式事务管理。
  10. @Transactional 注解: Spring 提供了 @Transactional 注解,可以将其应用到方法上,实现声明式事务管理。你可以在方法上使用该注解来指定事务的传播行为、隔离级别等属性。

使用 Spring 的事务管理,你可以轻松地处理事务,保证数据的一致性和完整性,同时降低代码的耦合度。无论是编程式事务管理还是声明式事务管理,Spring 都提供了丰富的支持和灵活的配置方式。

2、编程式事务控制

2.1、简介

编程式事务控制是一种通过在代码中显式编写事务管理代码来管理事务的方法。在这种方式下,开发人员直接在代码中控制事务的开始、提交和回滚,以确保一组操作的原子性和一致性。虽然相对于声明式事务管理而言,编程式事务管理可能更为繁琐,但它提供了更大的灵活性和细粒度的控制。

以下是编程式事务控制的关键要点:

  1. 事务管理器(Transaction Manager): 编程式事务控制仍然需要使用事务管理器来协调和管理事务。事务管理器负责处理底层数据库连接以及事务的开始、提交和回滚。
  2. 编写事务管理代码: 在需要进行事务管理的方法中,开发人员需要编写代码来显式地控制事务的开始、提交和回滚。通常,你需要获取事务管理器的句柄,并使用它来开启和提交事务。
  3. 事务操作流程: 编程式事务控制的典型操作流程包括:
  • 获取事务管理器的句柄。
  • 调用事务管理器的 getTransaction 方法获取事务对象。
  • 通过事务对象的方法来控制事务的开始、提交和回滚。
  • 在事务处理过程中捕获可能出现的异常,并根据情况进行回滚。
  1. 细粒度控制: 编程式事务管理允许你对每个方法或方法中的一部分代码进行细粒度的事务控制。这对于需要灵活控制事务的特定业务场景非常有用。
  2. 适用场景: 编程式事务控制适用于需要复杂事务逻辑、嵌套事务、或者需要根据条件来动态控制事务的情况。它也可以用于需要精细控制事务边界的情况。

尽管编程式事务控制在某些情况下可以提供更大的灵活性,但它通常会导致代码与事务管理的耦合增加,同时也增加了代码的复杂性。

与之相比,声明式事务管理通过 AOP 技术将事务管理逻辑从业务代码中解耦,提供了更清晰和简洁的事务管理方式。选择编程式还是声明式事务控制取决于项目需求和复杂性。

2.2、相关对象

对于编程式事务控制,重点要了解的是编程式事务控制的相关对象。

相关对象

描述

PlatformTransactionManager

事务管理器,负责管理事务的启动、提交和回滚。

TransactionDefinition

定义事务的属性,如传播行为、隔离级别、超时等。

TransactionStatus

表示事务的当前状态,包括活动、提交、回滚等。

TransactionTemplate

Spring 提供的工具类,用于简化编程式事务控制的使用。

2.2.1、PlatformTransactionManager

PlatformTransactionManager 接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法。

方法

说明

TransactionStatus

getTransaction(TransactionDefination defination)

获取事务的状态信息

void commit(TransactionStatus status)

提交事务

void rollback(TransactionStatus status)

回滚事务

注意:

PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类,例如:Dao 层技术是jdbc 或 mybatis 时:org.springframework.jdbc.datasource.DataSourceTransactionManager

Dao 层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager

2.2.2、TransactionDefinition

TransactionDefinition 是事务的定义信息对象,里面有如下方法:

方法

说明

int getIsolationLevel()

获得事务的隔离级别

int getPropogationBehavior()

获得事务的传播行为

int getTimeout()

获得超时时间

boolean isReadOnly()

是否只读

2.2.2.1、事务隔离级别

设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。

ISOLATION_DEFAULT

ISOLATION_READ_UNCOMMITTED

ISOLATION_READ_COMMITTED

ISOLATION_REPEATABLE_READ

ISOLATION_SERIALIZABLE

这里介绍一下不同的事务隔离级别:

  1. ISOLATION_DEFAULT(默认隔离级别): 使用数据库默认的隔离级别。具体隔离级别取决于底层数据库的默认设置。
  2. ISOLATION_READ_UNCOMMITTED(读未提交): 允许事务读取其他未提交事务的数据。这可能会导致脏读、不可重复读和幻读问题。
  3. ISOLATION_READ_COMMITTED(读已提交): 保证事务只能读取已经提交的数据。可以防止脏读,但可能会导致不可重复读和幻读问题。
  4. ISOLATION_REPEATABLE_READ(可重复读): 保证在事务执行期间,多次读取同一数据会得到相同的结果。可以防止脏读和不可重复读,但可能会导致幻读问题。
  5. ISOLATION_SERIALIZABLE(串行化): 最高的隔离级别,确保事务彼此完全隔离,不会出现脏读、不可重复读和幻读问题。但是并发性能较差,因为它会限制并发访问数据库。

事务隔离级别决定了在并发事务执行时,一个事务能否看到其他事务的未提交数据以及如何处理数据的一致性问题。不同的隔离级别提供了不同的权衡,可以根据应用程序的需求来选择适当的隔离级别。需要注意的是,更高的隔离级别通常会增加数据库的锁竞争,可能会影响并发性能。

2.2.2.2、事务传播行为

REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)

SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)

MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常

REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

NEVER:以非事务方式运行,如果当前存在事务,抛出异常

NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作

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

是否只读:建议查询时设置为只读

2.2.3、TransactionStatus

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

方法

说明

boolean hasSavepoint()

是否存储回滚点

boolean isCompleted()

事务是否完成

boolean isNewTransaction()

是否是新事务

boolean isRollbackOnly()

事务是否回滚

3、声明式事务控制

3.1、简介

声明式事务控制是一种使用元数据(例如注解或 XML 配置)来定义事务的行为,从而将事务管理逻辑从业务代码中分离出来的方法。

在声明式事务控制中,开发人员不需要显式编写事务管理代码,而是通过配置来指定事务的属性,如传播行为、隔离级别、超时等。Spring 框架负责根据配置来自动管理事务的启动、提交和回滚。

与之相反,编程式事务控制是通过在代码中显式编写事务管理代码来管理事务的方法。在编程式事务控制中,开发人员需要调用事务管理器的方法来开启、提交和回滚事务,以及处理异常情况。

3.2、区别

以下是声明式事务控制与编程式事务控制之间的主要区别:

  1. 代码分离:
  • 声明式事务控制:事务管理逻辑与业务逻辑分离,通过配置元数据实现,业务代码不涉及事务管理。
  • 编程式事务控制:事务管理逻辑与业务逻辑混合在一起,需要在业务代码中显式编写事务管理代码。
  1. 灵活性和复杂性:
  • 声明式事务控制:提供了更高的灵活性,可以在配置中更改事务属性,而无需更改业务代码。适用于大多数常见的事务场景。
  • 编程式事务控制:更灵活的控制,但可能导致代码与事务管理的紧耦合,增加代码复杂性。
  1. 可读性和维护性:
  • 声明式事务控制:提高了代码的可读性和维护性,事务管理逻辑集中在配置中,业务逻辑更清晰。
  • 编程式事务控制:可能导致代码重复,增加了代码的冗余度。
  1. 适用场景:
  • 声明式事务控制:适用于大多数常见的事务场景,可以简化事务管理,减少冗余代码。
  • 编程式事务控制:适用于需要更细粒度控制事务、嵌套事务、动态事务等复杂场景。

总之,声明式事务控制通过将事务管理逻辑从业务代码中分离出来,提供了更加清晰、可维护的事务管理方式。编程式事务控制更加灵活,但可能会导致代码复杂性增加。选择何种方式取决于项目需求和开发团队的偏好。

3.3、⭐作用

声明式事务处理的作用:

事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可

②在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便

注意Spring 声明式事务控制底层就是AOP。

下面分别对XML和注解进行分析,这是在“ATM转账业务”的基础上进行业务模拟。

首先是要创建实体类,然后创建对应的数据库表单,然后创建多层包:controller、service、dao、domain,最后是编写各个层的接口方法和实现方法,具体如下:

下面开始对事务控制代码进行配置,分别对XML和注解进行分析:

3.4、🔺基于xml

实现步骤:

① 引入tx命名空间

② 配置事务增强

③ 配置事务 AOP 织入

④ 测试事务控制转账业务代码

3.4.1、引入tx命名空间

3.4.2、配置事务增强

3.4.3、配置事务AOP织入

3.4.4、测试业务代码

在业务层方法中手动制造异常,如果发现数据库表单中的数据没有变化,则说明xml配置事务控制成功了。

3.4.5、⭐🔺切点方法配置

切点方法的事务参数的配置,主要就是对事务增强的配置:

其中,<tx:method> 代表切点方法的事务参数的配置,例如:

<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/>

参数如下:

name:切点方法名称

isolation:事务的隔离级别

propogation:事务的传播行为

timeout:超时时间

read-only:是否只读

3.5、🔺基于注解

注解和xml配置的最大不同在于,注解使用@Transactional替换掉了xml配置中的配置增强通知和配置织入的步骤,即:

3.5.1、配置组件扫描和注解驱动

3.5.2、注解替代

在各个类上配置上对应的注解,用于替代之前使用xml配置的各种bean。

3.5.3、@Transactional

在业务层的方法上面添加@Transactional,可配置参数也可不配:

3.5.4、注意事项

① 使用 @Transactional 在需要进行事务控制的类或是方法上修饰,注解可用的属性同 xml 配置方式,例如隔离级别、传播行为等。

② 注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置。

③ 使用在方法上,不同的方法可以采用不同的事务参数配置。

④ Xml配置文件中要开启事务的注解驱动<tx:annotation-driven />

相关文章
|
4月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
5月前
|
Java 关系型数据库 MySQL
Spring 事务失效场景总结
Spring 事务失效场景总结
65 4
|
23天前
|
Java 开发者 Spring
Spring高手之路24——事务类型及传播行为实战指南
本篇文章深入探讨了Spring中的事务管理,特别是事务传播行为(如REQUIRES_NEW和NESTED)的应用与区别。通过详实的示例和优化的时序图,全面解析如何在实际项目中使用这些高级事务控制技巧,以提升开发者的Spring事务管理能力。
39 1
Spring高手之路24——事务类型及传播行为实战指南
|
17天前
|
XML Java 数据库连接
Spring中的事务是如何实现的
Spring中的事务管理机制通过一系列强大的功能和灵活的配置选项,为开发者提供了高效且可靠的事务处理手段。无论是通过注解还是AOP配置,Spring都能轻松实现复杂的事务管理需求。掌握这些工具和最佳实践,能
30 3
|
3月前
|
Java 数据库连接 数据库
spring复习05,spring整合mybatis,声明式事务
这篇文章详细介绍了如何在Spring框架中整合MyBatis以及如何配置声明式事务。主要内容包括:在Maven项目中添加依赖、创建实体类和Mapper接口、配置MyBatis核心配置文件和映射文件、配置数据源、创建sqlSessionFactory和sqlSessionTemplate、实现Mapper接口、配置声明式事务以及测试使用。此外,还解释了声明式事务的传播行为、隔离级别、只读提示和事务超时期间等概念。
spring复习05,spring整合mybatis,声明式事务
|
3月前
|
Java 测试技术 数据库
Spring事务传播机制(最全示例)
在使用Spring框架进行开发时,`service`层的方法通常带有事务。本文详细探讨了Spring事务在多个方法间的传播机制,主要包括7种传播类型:`REQUIRED`、`SUPPORTS`、`MANDATORY`、`REQUIRES_NEW`、`NOT_SUPPORTED`、`NEVER` 和 `NESTED`。通过示例代码和数据库插入测试,逐一展示了每种类型的运作方式。例如,`REQUIRED`表示如果当前存在事务则加入该事务,否则创建新事务;`SUPPORTS`表示如果当前存在事务则加入,否则以非事务方式执行;`MANDATORY`表示必须在现有事务中运行,否则抛出异常;
158 4
Spring事务传播机制(最全示例)
|
2月前
|
Java 关系型数据库 MySQL
Spring事务失效,我总结了这7个主要原因
本文详细探讨了Spring事务在日常开发中常见的七个失效原因,包括数据库不支持事务、类不受Spring管理、事务方法非public、异常被捕获、`rollbackFor`属性配置错误、方法内部调用事务方法及事务传播属性使用不当。通过具体示例和源码分析,帮助开发者更好地理解和应用Spring事务机制,避免线上事故。适合所有使用Spring进行业务开发的工程师参考。
34 2
|
2月前
|
Java 程序员 Spring
Spring事务的1道面试题
每次聊起Spring事务,好像很熟悉,又好像很陌生。本篇通过一道面试题和一些实践,来拆解几个Spring事务的常见坑点。
Spring事务的1道面试题
|
3月前
|
Java Spring
Spring 事务传播机制是什么?
Spring 事务传播机制是什么?
23 4
|
2月前
|
监控 Java 数据库
Spring事务中的@Transactional注解剖析
通过上述分析,可以看到 `@Transactional`注解在Spring框架中扮演着关键角色,它简化了事务管理的复杂度,让开发者能够更加专注于业务逻辑本身。合理运用并理解其背后的机制,对于构建稳定、高效的Java企业应用至关重要。
62 0