Spring的两种事务管理机制的基本概念和demo示例

 更新时间:2023年07月17日 10:36:55   作者:小威要向诸佬学习呀  
Spring事务包括声明式事务管理和注解式事务管理,我们通过概念和小demo的形式一步一步地来一起学习这个知识点,需要的朋友可以参考下

声明式事务管理

首先简单介绍下Spring的声明式事务管理:

声明式事务管理是指通过配置来实现事务管理,我们只需定义事务边界和事务属性,不需要显式编写事务管理的代码。

那么我们如何实现呢?

首先配置事务管理器和数据源:通过配置 <bean> 元素,使用 TransactionManager 类型的 Bean 来提供事务管理器的实例,并使用 DataSource 类型的 Bean 来提供数据源。

接着定义事务边界:使用 <tx:advice> 元素来定义事务边界和事务属性,指定哪些方法需要进行事务管理。

还需要配置事务通知:使用 <aop:config> 元素来启用事务管理功能并将事务通知应用到指定的切入点上。

注解式管理事务

除了上面提到的声明式管理之外,Spring提供了一种更加简单且强大的方式来管理事务,通过使用注解式事务,可以在方法级别上进行声明和配置事务的行为。这块面试官问的更多,我们来详细介绍下:

@Transactional注解(核心注解): @Transactional是Spring中最常用的注解之一,用于标识需要进行事务管理的方法或类。它可以应用在方法上或类上,而且还可以配置这些属性:

  1. value:指定事务管理器的名称(如果有多个事务管理器)。
  2. propagation:指定事务传播行为,默认值为REQUIRED。
  3. isolation:指定事务隔离级别,默认值为DEFAULT
  4. readOnly:指定事务是否为只读事务,默认值为false。
  5. timeout:指定事务超时时间,默认值为-1,表示不设置超时。

事务传播行为

上面介绍了Spring实现事务的两种方式,接下来介绍下另一个重量级的知识点–》事务传播行为。

事务传播行为定义了当一个事务方法调用另一个事务方法时,如何处理事务的范围。Spring提供了多种传播行为选项,包括:

  1. REQUIRED:如果当前没有事务,则创建一个新的事务;如果已存在事务,则加入到当前事务中。
  2. REQUIRES_NEW:每次都会创建一个新的事务,如果已存在事务则将其挂起。
  3. SUPPORTS:如果当前存在事务,则加入到当前事务中;如果没有事务,则以非事务方式执行。
  4. NOT_SUPPORTED:以非事务方式执行方法,如果当前存在事务则将其挂起。
  5. NEVER:以非事务方式执行方法,如果当前存在事务则抛出异常。
  6. MANDATORY:如果当前存在事务,则加入到当前事务中;如果没有事务,则抛出异常。
  7. NESTED:如果当前存在事务,则将该事务嵌套到当前事务中作为一个保存点,可以回滚到该保存点。

事务隔离级别

接下来介绍下 spring的事务隔离级别,这一块也是面试官经常问到的一点。它与数据库的事务隔离级别有着异曲同工之妙。

事务隔离级别定义了多个事务同时运行时彼此之间的可见性和影响范围。Spring支持以下事务隔离级别:

  • DEFAULT:使用数据库默认的事务隔离级别。
  • READ_UNCOMMITTED:最低级别的隔离级别,允许读取未提交的数据。
  • READ_COMMITTED:允许读取已提交的数据。
  • REPEATABLE_READ:对同一数据的多次读取结果保持一致,避免脏读和不可重复读。
  • SERIALIZABLE:最高级别的隔离级别,确保事务串行执行,避免任何并发问题。
  • 只读事务(readOnly): 如果一个事务中的方法仅执行读操作而不进行写操作时,可以将事务标记为只读事务。这样做可以提高性能,因为只读事务不需要对数据进行锁定。

学生管理系统demo

如果上面的概念看着有点懵,那么接下来让我们通过一个学生管理系统的demo来详细介绍 Spring 的声明式事务和基于注解的事务管理。

我从项目中扒出来部分伪代码,现在我们有一个简单的学生管理系统,其中包含两个服务方法:addStudent() 和 updateStudent()。addStudent() 方法用于添加学生信息,updateStudent() 方法用于更新学生信息。

使用声明式事务管理demo

前面概念部分提到过,在声明式事务管理中,我们可以使用 XML 配置来定义事务边界和事务特性。

首先,我们需要配置事务管理器和数据源。在 Spring 配置文件中,我们可以使用 TransactionManager 元素和 DataSource 元素来配置相应的 Bean。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <!-- 数据源配置 -->
</bean>

接下来,定义事务边界,我们可以在服务类中使用 :

<bean id="studentService" class="com.test.StudentService">
    <!-- 依赖注入 -->
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="add*" propagation="REQUIRED" />
        <tx:method name="update*" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="studentServicePointcut" expression="execution(* com.example.StudentService.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="studentServicePointcut" />
</aop:config>

在上面的代码中,我们使用了 <tx:advice> 元素来配置事务边界。通过 <tx:method> 元素,我们可以指定需要进行事务管理的方法并定义事务传播行为。

最后,在 Spring 配置文件中,我们需要启用事务管理功能并配置事务通知。

<tx:annotation-driven transaction-manager="transactionManager" />

我们配置了以上代码,因此Spring 会自动扫描带有 @Transactional 注解的方法,并生成事务通知。

使用注解的事务管理demo

首先第一步也是配置事务管理器和数据源,这一步与声明式事务管理相同,因此不在赘述。

接着定义事务边界,这点与声明式事务管理相比,基于注解的事务管理不再需要在 Spring 配置文件中进行额外的配置。我们只需在服务类中使用 @Transactional 注解即可。

@Service
public class StudentService {
    // ...
    @Transactional
    public void addStudent(Student student) {
        // 添加学生信息,管理系统伪代码省略
    }
    @Transactional
    public void updateStudent(Student student) {
        // 更新学生信息,管理系统伪代码省略
    }
    // ...
}

通过添加 @Transactional 注解到服务类中的方法上,我们直接就实现了对 addStudent() 和 updateStudent() 方法的事务管理。

同时,我们也可以将 @Transactional 注解应用到接口定义或抽象类的方法上,以便在子类中继承和覆盖时继续享受事务管理功能。

面试这样答

声明式事务管理和基于注解的事务管理是 Spring 提供的两种常用事务管理方式。它们都能够简化事务管理的配置和编写,并提供了灵活的事务特性。

在声明式事务管理中,我们使用 XML 配置或注解来定义事务边界和事务通知。通过使用 <tx:advice> 元素和 <tx:method> 元素,我们可以指定需要进行事务管理的方法并定义事务传播行为。

而基于注解的事务管理更加简洁,只需在服务类的方法上添加 @Transactional 注解即可实现事务管理。

无论是哪种方式,Spring 的事务管理机制都使得我们能够轻松实现数据的一致性和完整性。通过合理配置事务特性,我们可以满足不同业务场景下的事务需求。

到此这篇关于Spring的两种事务管理机制的基本概念和demo示例的文章就介绍到这了,更多相关Spring的两种事务管理机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用System.exit()来优雅地终止SpringBoot项目的代码示例

    使用System.exit()来优雅地终止SpringBoot项目的代码示例

    System.exit() 方法是 Java 中用于退出程序的方法,它接受一个整数参数,通常被用来指示程序的退出状态,本文给大家介绍了如何使用System.exit()来优雅地终止SpringBoot项目,需要的朋友可以参考下
    2024-08-08
  • springboot中shiro使用自定义注解屏蔽接口鉴权实现

    springboot中shiro使用自定义注解屏蔽接口鉴权实现

    本文主要介绍了springboot中shiro使用自定义注解屏蔽接口鉴权实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 解读Map中的computeIfAbsent方法

    解读Map中的computeIfAbsent方法

    文章介绍了Java 8中Map接口的computeIfAbsent方法,该方法用于在Map中获取指定键的值,如果不存在则调用提供的函数计算值并放入Map中,并给出了使用示例
    2026-05-05
  • 详解HttpSecurity是如何组装过滤器链的

    详解HttpSecurity是如何组装过滤器链的

    HttpSecurity 本质上也是一个 SecurityBuilder,我们平时在 HttpSecurity 配置的各种东西,本质上其实就是一个 xxxConfigure,这些 xxxConfigure 被 HttpSecurity 收集起来,本文将给大家介绍HttpSecurity是如何组装过滤器链的,需要的朋友可以参考下
    2024-06-06
  • 如何利用rabbitMq的死信队列实现延时消息

    如何利用rabbitMq的死信队列实现延时消息

    这篇文章主要介绍了如何利用rabbitMq的死信队列实现延时消息问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Springboot自动装配之注入DispatcherServlet的实现方法

    Springboot自动装配之注入DispatcherServlet的实现方法

    这篇文章主要介绍了Springboot自动装配之注入DispatcherServlet,Springboot向外界提供web服务,底层依赖了springframework中的web模块来实现,那么springboot在什么时机向容器注入DispatcherServlet这个核心类的呢?带着这个问题一起通过本文学习吧
    2022-05-05
  • Springboot之Jasypt配置文件加密/解密方式

    Springboot之Jasypt配置文件加密/解密方式

    Jasypt是一个用于Java项目加密敏感信息的库,可以避免敏感信息泄露,文章介绍了如何在Spring Boot项目中整合Jasypt,并提供了一些防止密码泄露的建议
    2026-03-03
  • MyBatis-Plus 分页插件配置的两种方式实现

    MyBatis-Plus 分页插件配置的两种方式实现

    本文主要介绍了MyBatis-Plus 分页插件配置的两种方式实现,包括使用PaginationInterceptor和MybatisPlusInterceptor两种方式,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • java中queue接口的使用详解

    java中queue接口的使用详解

    本篇文章主要介绍了java中queue接口的使用详解,对学习Queue接口有一定的帮助,感兴趣的小伙伴们可以参考一下。
    2016-11-11
  • Java链表(Linked List)基本原理与实现方法入门示例

    Java链表(Linked List)基本原理与实现方法入门示例

    这篇文章主要介绍了Java链表(Linked List)基本原理与实现方法,结合实例形式分析了Java链表(Linked List)的功能、原理、实现方法与操作注意事项,需要的朋友可以参考下
    2020-03-03

最新评论