spring_boot全局事务设置
2021
05.27

spring_boot全局事务设置

一、简介:

在我们平常开发中,常需要用到事务。例如账单等数据,一旦出现错误,需要将之前的插入的数据进行回归。这里事务主分为2种,一种是直接在对应的逻辑上添加@Transactional注解即可,但是对于异常需要@Transactional(rollbackFor = {Exception.class}) 捕获回滚。这个才可以,但是这个有个缺点,就是需要在所有的service层上都加才行。所以是极为不方便的,所以我们这里用全局设置,给所有的service层加上事务,这样不用一个个加了

二、逻辑:

这里我们可以通过spring AOP 的方式去实现,及扫码所有文件,根据我们设定的模糊路径和匹配的模糊java名称进行设置,对其中的模糊方法名,进行特别的事务级别及规定进行特殊设定。

三、实现:

这里我们直接上代码:

                    

1.需要先引入对应的依赖。

   

 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

 

2.编写配置文件。

 

package org.springcrazy.common.config;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.interceptor.*;

import java.util.Collections;


/**
 * 全局事务统一配置
 *
 */
@Slf4j
@Aspect
@Component
public class TransactionAdviceConfig {
    public static final String aop_pointcut_expression = "execution(* org.springcrazy.modules.*.service.impl.*.*(..))";

    @Autowired
    PlatformTransactionManager transactionManager;

    @Bean
    public TransactionInterceptor txAdvice() {

        //增删改使用PROPAGATION_REQUIRED 当前有事务则加入该事务,没有事务则创建事务
        RuleBasedTransactionAttribute txAttr_REQUIRED = new RuleBasedTransactionAttribute();
        //事务回滚机制
        txAttr_REQUIRED.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        //事务隔离机制
        txAttr_REQUIRED.setIsolationLevel(Isolation.DEFAULT.value());

        //读使用PROPAGATION_SUPPORTS 当前有事务则加入该事务,没有事务则以非实物方式运行
        DefaultTransactionAttribute txAttr_SUPPORTS_READONLY = new DefaultTransactionAttribute();
        //事务回滚机制
        txAttr_SUPPORTS_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
        //事务隔离机制
        txAttr_SUPPORTS_READONLY.setIsolationLevel(Isolation.DEFAULT.value());
        txAttr_SUPPORTS_READONLY.setReadOnly(true);

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        //这里添加方法的事务运行机制 名字以add开通的方法走这个
        source.addTransactionalMethod("add*", txAttr_REQUIRED);

        //设置的方法的事务运行机制 名字以get开通的方法走这个
        source.addTransactionalMethod("get*", txAttr_SUPPORTS_READONLY);
//设置其他方法的事务运行机制
        source.addTransactionalMethod("*", txAttr_SUPPORTS_READONLY);
        return new TransactionInterceptor(transactionManager, source);
    }

    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

//加入扫码文件的规则
        pointcut.setExpression(aop_pointcut_expression);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}

 

 

 

这里需要注意几个点

1.这里的文件路径,一定要指定到继承service的Impl的位置。

 

 

如果您的serviceImpl没有依照一定的规则进行创建。则就无法进行全部设定。例如我的都是在org.springcrazy.modules.XX.service.impl下。*号代表所有名称。*(..)代表所有的有参或无参的方法。

则我的扫码路径则为

*  org.springcrazy.modules.*.service.impl.*.*(..)

注意这里的的第一个*与后面的文件名一定之间要有空格。

 

 

spring在TransactionDefinition中规定了7种类型的事务行为。规定了具体的事务需要怎么进行调用

PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。

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

PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。

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

PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

 

这里我们增删改都用的是PROPAGATION_REQUIRED这个最常用的。而查询我们用PROPAGATION_SUPPORTS。

 

之后我们就可以测试。例如写一个批量添加的方法。对库进行操作。正常情况没有事务时,如果批量操作中某个报错。则之前添加的不回回滚,但是加上事务则可进行回滚操作,但是有些值例如主键,大部分主键都带有自增,如果出现回滚,但是自增值不会进行回滚的。也就是我们加10个值,第5个报错了。没有事务的则数据会停留子第四个插入的。自增值为5。加入事务后,数据一个都不会插入,但是自增值依旧停留在5。

热门文章
1
通过微信接口获取code
6932浏览 2021-04-14 09:26
2
Java实现html页面抓取转PDF
3989浏览 2021-04-13 17:09
3
vue 页面按钮点击复制内容
2945浏览 2021-04-21 09:42
4
对接父子级数据的添加或修改逻辑
2896浏览 2021-04-21 09:47
5
Mysql常用sql语句
2721浏览 2021-04-20 10:46
6
邀请函│EICD2021中国民办教育大会
2045浏览 2021-03-15 14:06
7
Linux安装中文字体
1956浏览 2021-04-13 17:14
8
合并单元格的方法
1682浏览 2021-04-14 09:23
9
vue中数组去重的实现
1594浏览 2021-04-14 09:20
10
Nginx如何配置重定向
1562浏览 2021-04-14 09:09