一文带你掌握Spring事务核心:TransactionDefinition详解!

简介: TransactionDefinition是Spring框架中用于定义事务属性的核心接口。在Spring的事务管理中,这个接口扮演着至关重要的角色,它允许开发者定制事务的各种属性,如隔离级别、传播行为、超时时间以及是否只读。

TransactionDefinition详解 - 程序员古德

TransactionDefinition是Spring框架中用于定义事务属性的核心接口。在Spring的事务管理中,这个接口扮演着至关重要的角色,它允许开发者定制事务的各种属性,如隔离级别、传播行为、超时时间以及是否只读。

基本介绍

TransactionDefinition 接口的主要方法:

  1. getIsolationLevel(): 返回事务的隔离级别。隔离级别定义了事务如何与其他事务隔离,以避免如脏读、不可重复读和幻读等问题。Spring 支持多种隔离级别,如 ISOLATION_DEFAULTISOLATION_READ_UNCOMMITTEDISOLATION_READ_COMMITTEDISOLATION_REPEATABLE_READISOLATION_SERIALIZABLE
  2. getPropagationBehavior(): 返回事务的传播行为。传播行为决定了当一个事务方法被另一个事务方法调用时,应该如何传播事务。例如,是否应该启动新的事务、使用现有事务还是挂起现有事务等。Spring 支持如 PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_NESTED 等多种传播行为。
  3. getTimeout(): 返回事务的超时时间(以秒为单位)。如果一个事务运行的时间超过了这个指定的时间,那么它可能会被底层的事务管理系统自动回滚。
  4. isReadOnly(): 返回事务是否为只读。一个只读事务意味着这个事务只读取数据但不修改数据。在某些情况下,数据库可以利用这个信息来优化性能。
  5. getName(): 返回事务的名称。这是一个可选属性,可以为事务提供一个名称,以便于识别和调试。

如下一个简单的 TransactionDefinition 案例:

/**
 * @版权 Copyright by 程序员古德 <br>
 * @创建人 程序员古德 <br>
 * @创建时间 2023/09/19 15:37 <br>
 */

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)  
public void someTransactionalMethod() {
   
     
    // ... business logic ...  
}

在上面的例子中,指定了事务的隔离级别为 READ_COMMITTED 和传播行为为 REQUIRES_NEW。总的来说,TransactionDefinition 接口为 Spring 提供了一种统一和灵活的方式来定义和配置事务的各种属性,使开发者能够根据不同的业务需求调整事务的行为。

场景介绍

电商系统订单处理

在电商系统中,当用户下单时,通常需要在数据库中创建订单记录,同时更新库存和用户的付款状态,这个过程必须是事务性的,以确保数据的一致性。这场景具有以下特点:

  1. 多个库表操作(创建订单、更新库存、更新付款状态)。
  2. 需要确保所有操作都成功才提交事务。

在该场景中 TransactionDefinition 的伪配置如下:

  • 传播行为PROPAGATION_REQUIRED,因为在一个事务上下文中执行所有操作是有意义的。
  • 隔离级别ISOLATION_READ_COMMITTED,以避免脏读,同时允许一定程度的并发。
  • 超时时间:根据业务需要设定,比如30秒。

银行转账系统

在银行转账系统中,从一个账户扣款并向另一个账户存款必须是一个原子操作,如果在扣款后因为某种原因存款失败,整个转账操作必须回滚。这场景具有以下特点:

  1. 涉及两个账户的数据库操作
  2. 需要确保转账操作的原子性

在该场景中 TransactionDefinition 的伪配置如下:

  • 传播行为PROPAGATION_REQUIRED,确保转账操作的原子性。
  • 隔离级别ISOLATION_SERIALIZABLE,因为金融系统通常需要最严格的隔离级别。
  • 超时时间:相对较长,比如60秒,因为金融交易可能涉及更多验证和处理时间。

内容管理系统

在内容管理系统中,发布一篇文章可能包括在数据库中创建文章记录、更新作者统计信息、发送通知等操作,这些操作需要在一个事务中执行,以确保数据的一致性。。这场景具有以下特点:

  1. 多个数据库和外部系统操作(如发送通知)
  2. 需要确保所有操作都成功才提交事务

在该场景中 TransactionDefinition 的伪配置如下:

  • 传播行为PROPAGATION_REQUIRED,以便在一个事务上下文中执行所有操作。
  • 隔离级别ISOLATION_READ_COMMITTED,以平衡性能和一致性。
  • 超时时间:相对较短,比如10秒,因为内容管理系统通常对性能要求较高。

代码案例

假设,我们正在开发一个简单的银行转账系统,需要确保转账操作的原子性。在案例中我们将使用Spring框架的事务管理功能,并通过TransactionDefinition来定义事务属性,核心代码如下:

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.jdbc.core.JdbcTemplate;  
import org.springframework.transaction.PlatformTransactionManager;  
import org.springframework.transaction.TransactionDefinition;  
import org.springframework.transaction.TransactionStatus;  
import org.springframework.transaction.support.DefaultTransactionDefinition;  

/**
 * @版权 Copyright by 程序员古德 <br>
 * @创建人 程序员古德 <br>
 * @创建时间 2023/09/19 15:37 <br>
 */
public class BankService {
   
     

    @Autowired  
    private PlatformTransactionManager transactionManager;  

    @Autowired  
    private JdbcTemplate jdbcTemplate;  

    public void transfer(String fromAccount, String toAccount, double amount) {
   
     
        // 定义一个事务属性对象  
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();  
        transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);  
        transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
        transactionDefinition.setTimeout(10); // 设置超时时间为10秒  
        transactionDefinition.setReadOnly(false); // 事务不是只读的  

        // 获取事务状态对象  
        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);  

        try {
   
     
            // 从源账户扣钱  
            jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE account_number = ?", amount, fromAccount);  
            // 向目标账户加钱  
            jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE account_number = ?", amount, toAccount);  

            // 提交事务  
            transactionManager.commit(transactionStatus);  
            System.out.println("转账成功!");  
        } catch (Exception e) {
   
     
            // 回滚事务  
            transactionManager.rollback(transactionStatus);  
            System.out.println("转账失败!");  
            throw e; // 或者选择记录错误日志等其他处理方式  
        }  
    }  
}

在这个案例中,我们定义了一个transfer方法,用于执行转账操作。

在方法内部,我们首先创建了一个DefaultTransactionDefinition对象,并通过setPropagationBehaviorsetIsolationLevelsetTimeoutsetReadOnly方法配置了事务的属性,然后,我们通过transactionManager.getTransaction方法获取了一个TransactionStatus对象,该对象代表了当前事务的状态,在try-catch块中,我们执行了实际的数据库操作(扣钱和加钱),并在成功的情况下提交事务,失败的情况下回滚事务。

最后,我们根据事务的执行结果输出相应的提示信息。

源码解读

这里列出了TransactionDefinition核心方法以及变量,其中一些功能含义、功能重复的就以... 其他XXX ... 进行表示,如下:

package org.springframework.transaction;  

import java.io.Serializable;  
/**
 * @版权 Copyright by 程序员古德 <br>
 * @创建人 程序员古德 <br>
 * @创建时间 2023/09/19 15:37 <br>
 */
/**  
 * 事务定义接口,用于定义事务的属性。  
 *  
 * @author Juergen Hoeller  
 * @since 16.03.2003  
 */  
public interface TransactionDefinition extends Serializable {
   
     

    /**  
     * 支持当前事务,如果当前没有事务,则新建一个事务。  
     * 这是最常见的选择。  
     */  
    int PROPAGATION_REQUIRED = 0;  

    //  

    /**  
     * 使用默认的事务隔离级别。  
     * 实际的隔离级别由底层数据库决定。  
     */  
    int ISOLATION_DEFAULT = -1;  

    // ... 其他隔离级别常量 ...  

    /**  
     * 返回事务的传播行为。  
     * <p>事务的传播行为决定了当在一个事务方法中被另一个事务方法调用时,如何使用事务。  
     * 例如:{@code PROPAGATION_REQUIRED}表示当前方法必须在事务中运行。如果当前存在事务,则加入该事务;  
     * 如果当前没有事务,则新建一个事务。</p>  
     * @return 事务的传播行为常量,如{@code PROPAGATION_REQUIRED}等。  
     */  
    int getPropagationBehavior();  

    /**  
     * 返回事务的隔离级别。  
     * <p>事务的隔离级别决定了事务如何处理并发问题。不同的隔离级别会影响脏读、不可重复读和幻读等问题。</p>  
     * @return 事务的隔离级别常量,如{@code ISOLATION_READ_COMMITTED}等。  
     */  
    int getIsolationLevel();  

    /**  
     * 返回事务的超时时间(以秒为单位)。  
     * <p>如果事务在规定的时间内没有完成,则会被自动回滚。</p>  
     * @return 超时时间(秒),默认值为-1,表示永不超时。  
     */  
    int getTimeout();  

    /**  
     * 返回事务是否为只读。  
     * <p>只读事务不会修改数据,因此可以进行一些优化。</p>  
     * @return 如果事务为只读,则返回{@code true};否则返回{@code false}。  
     */  
    boolean isReadOnly();  

    /**  
     * 返回事务的名称。  
     * <p>事务名称可以用于日志记录、监控和调试。</p>  
     * @return 事务的名称,如果没有设置则返回{@code null}。  
     */  
    String getName();  
}

核心总结

TransactionDefinitionSpring框架中用于定义事务属性的核心接口,为开发者提供了事务管理的标准化方式。通过它,我们可以设置事务的传播行为、隔离级别、超时时间和只读属性等,确保数据在并发场景中的一致性和完整性。在实际应用中,TransactionDefinition与其他Spring组件如PlatformTransactionManager结合使用,为数据库操作提供了原子性、一致性、隔离性和持久性的保障,是构建健壮、可维护企业级应用的关键。熟悉并正确使用TransactionDefinition,对于提高系统性能和数据安全性具有重要意义。

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