Spring Boot教程(六):spring boot事务管理

一、事务管理简介

所有的数据访问技术都离不开事务处理,否则将会造成数据不一致,在目前企业级应用开发中,事务管理是必不可少的。数据库事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。

通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的 ACID(原子性、一致性、隔离性和持久性)属性,事务是数据库运行中的逻辑工作单位,由数据库中的事务管理子系统负责事务的处理。

首先需要明确的一点是 Spring Boot 事务机制实质上就是 Spring 的事务机制,是采用统一的机制处理来自不同数据访问技术的事务处理,只不过 Spring Boot 基于自动配置的特性作了部分处理来节省开发者的配置工作。

Spring 事务管理分两种方式:

  • 编程式事务,指的是通过编码方式实现事务。
  • 声明式事务,基于 AOP,将具体业务逻辑与事务处理解耦。这是建议采用的方式。

二、声明式事务

声明式事务是建立在 AOP 机制之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点,就是通过 AOP 机制将具体业务逻辑与事务处理解耦,不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,因此在实际使用中声明式事务用的比较多。

声明式事务有两种方式:一种是在 XML 配置文件中做相关的事务规则声明;另一种是基于 @Transactional 注解的方式(@Transactional 注解是来自 org.springframework.transaction.annotation 包),便可以将事务规则应用到业务逻辑中。

在 SpringBoot 中,建议采用注解 @Transactional 进行事务的控制,只需要在需要进行事务管理的方法或者类上添加 @Transactional 注解即可,接下来我们来通过代码讲解。

首先新建 service 包作为业务代码包,事务处理一般在 service 层做,当然在 controller 层中处理也可以,但是建议还是在业务层进行处理,之后在包中新建 TransactionTestService 类,代码如下:

package com.wang.service;

import com.wang.dao.AuthorDao;
import com.wang.entity.Author;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
public class TransactionTestService {
    
    
    @Resource
    AuthorDao authorDao;

    public Boolean test1() {
    
    
        Author author = new Author();
       author.setPassword("test1-password");
       author.setName("test1_name");
       author.setId("test1_id");
        // 在数据库表中新增一条记录
        authorDao.addAuthor(author);
        // 发生异常
        System.out.println(1/0);
        return true;
    }

    @Transactional
    public Boolean test2() {
    
    
        Author author = new Author();
        author.setPassword("test2-password");
        author.setName("test2_name");
        author.setId("test2_id");
        // 在数据库表中新增一条记录
        authorDao.addAuthor(author);
        // 发生异常
        System.out.println(1/0);
        return true;
    }
}

首先在类上添加 @Service 将其注册到 IOC 容器中管理,之后注入 UserDao 对象以实现后续的数据层操作,最后实现两个业务方法 test1() 和 test2(),二者实现类似,只是两个方法添加的用户对象名称和密码字符串不同,且 test2() 方法上添加了 @Transactional 注解,而 test1() 方法上并没有添加,在方法中我们都添加了一句代码,让数字 1 去除以 数字 0,这段代码一定会出现异常,我们用这个来模拟在发生异常时事务处理能否成功。

按照正常理解,在执行 SQL 语句后,一旦发生异常,这次数据库更改一定会被事务进行回滚,正常情况下数据库中会有 test1 的数据而没有 test2 的数据,因为 test1() 方法并没有纳入事务管理中,而 test2() 方法由于加上了 @Transactional 注解是会被事务管理器处理的。

感兴趣的可以自己写代码测试一下效果。

另外,@Transactional 不仅可以注解在方法上,也可以注解在类上。当注解在类上时,意味着此类的所有 public 方法都是开启事务的。如果类级别和方法级别同时使用了 @Transactional 注解,则使用在类级别的注解会重载方法级别的注解。

猜你喜欢

转载自blog.csdn.net/Tracycoder/article/details/113940200
今日推荐