@Transactional注解异常报错之多数据源详解

目录
  • @Transactional注解报错之多数据源
    • 1.在配置数据源的同时
    • 2.一定要在需要使用事物注解的数据源配置里
  • @Transactional 错误使用的几种场景

@Transactional注解报错之多数据源

如果在加上@Transactional注解之后报错,先查看程序是否为多数据源,之前专门有一章讲解springboot的多数据源实现。多数据源的情况下加事物注解,有可能会出现问题,以下是解决方案。

1.在配置数据源的同时

一定到在其中一个配置上加上@Primary注解,其他的不要加。

package com.wys.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
/**
 * @program:
 * @description: 数据库配置1
 * @author: wys
 * @create: 2019-12-03 16:20
 **/
@Configuration
@MapperScan(basePackages = "com.wys.mapper.**", sqlSessionFactoryRef = "oneSqlSessionFactory")
public class OneDataSourceConfig {
    @Value("${spring.datasource.one.driver-class-name}")
    String driverClass;
    @Value("${spring.datasource.one.url}")
    String url;
    @Value("${spring.datasource.one.username}")
    String userName;
    @Value("${spring.datasource.one.password}")
    String passWord;
    @Primary
    @Bean(name = "oneDataSource")
    @ConfigurationProperties("spring.datasource.one")
    public DataSource masterDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(passWord);
        return dataSource;
    }
    @Bean(name = "oneSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mybatis/mapper-postgre/*.xml"));
        return sessionFactoryBean.getObject();
    }
    @Bean(name = "oneSqlSessionFactory")
    public SqlSessionTemplate sqlSessionFactoryTemplate(@Qualifier("oneSqlSessionFactory")SqlSessionFactory sqlSessionFactory ) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

2.一定要在需要使用事物注解的数据源配置里

加上创建事务管理器

package com.wys.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
/**
 * @program:
 * @description: 数据库配置1
 * @author: wys
 * @create: 2019-12-03 16:20
 **/
@Configuration
@MapperScan(basePackages = "com.wys.mapper.**", sqlSessionFactoryRef = "oneSqlSessionFactory")
public class OneDataSourceConfig {
    @Value("${spring.datasource.one.driver-class-name}")
    String driverClass;
    @Value("${spring.datasource.one.url}")
    String url;
    @Value("${spring.datasource.one.username}")
    String userName;
    @Value("${spring.datasource.one.password}")
    String passWord;
    @Primary
    @Bean(name = "oneDataSource")
    @ConfigurationProperties("spring.datasource.one")
    public DataSource masterDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(passWord);
        return dataSource;
    }
    @Bean(name = "oneSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mybatis/mapper-postgre/*.xml"));
        return sessionFactoryBean.getObject();
    }
    /
 // 创建事务管理器1
    @Bean(name = "oneManager1")
    public PlatformTransactionManager txManager(@Qualifier("oneDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
/////////////////////////
    @Bean(name = "oneSqlSessionFactory")
    public SqlSessionTemplate sqlSessionFactoryTemplate(@Qualifier("oneSqlSessionFactory")SqlSessionFactory sqlSessionFactory ) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

在需要加注解的地方加上transactionManager 配置即可。

@Transactional(transactionManager ="oneManager1",rollbackFor=Exception.class)

@Transactional 错误使用的几种场景

@RestController
public class AController {
    @Autowired
    AService aService;

    // 回滚
    @GetMapping("direct")
    public void direct() {
        aService.testTransactional();
    }

    // 不回滚
    @GetMapping("indirect")
    public void indirect() {
        aService.testTransactionalIndirect();
    }

    // 不回滚
    @GetMapping("nonPublic")
    public void nonPublic() {
        aService.testTransactionalNonPublic();
    }

    // 不回滚
    @GetMapping("catchException")
    public void catchException() {
        aService.testTransactionalCatchException();
    }

    // 不回滚
    @GetMapping("sqlException")
    public void sqlException() throws SQLException {
        aService.testTransactionalSQLException();
    }

    // 回滚
    @GetMapping("sqlExceptionWithRollbackfor")
    public void sqlExceptionWithRollbackfor() throws SQLException {
        aService.testTransactionalSQLExceptionWithRollbackfor();
    }
}
@Service
public class AService {
    @Autowired
    TestTableDAO testTableDAO;

    // 回滚
    @Transactional
    public void testTransactional() {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);
        throw new RuntimeException("exception");
    }

    // 不回滚: 类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰
    public void testTransactionalIndirect() {
        testTransactional();
    }

    // 不回滚: @Transaction注解只对方法名为pubic的才生效
    @Transactional
    void testTransactionalNonPublic() {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);
        throw new RuntimeException("exception");
    }

    // 不回滚
    @Transactional
    public void testTransactionalCatchException() {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);
        try {
            throw new RuntimeException("exception");
        } catch (Exception e) {
            System.out.println("catch");
        }
    }

    // 不回滚: @Transactional默认情况下只回滚RuntimeException和Error
    @Transactional
    public void testTransactionalSQLException() throws SQLException {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);
        throw new SQLException("exception");
    }

    // 回滚: 指定在 SQLException 异常发生时回滚
    @Transactional(rollbackFor = {
            SQLException.class
    })
    public void testTransactionalSQLExceptionWithRollbackfor() throws SQLException {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);
        throw new SQLException("exception");
    }
}
@Repository
public interface TestTableDAO
        extends JpaRepository<ATestTable, Integer>, JpaSpecificationExecutor<ATestTable> {
}
@Entity
@Data
@Table(name = "test")
public class ATestTable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;

    @Column(name = "summary", length = 512)
    String summary;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • @Transactional跟@DS动态数据源注解冲突的解决

    目录 @Transactional跟@DS动态数据源注解冲突 背景 @Transactional执行流程 解决方法 动态数据源切换失败 由事务@Transactional注解导致动态数据源切换失效的问题 @Transactional跟@DS动态数据源注解冲突 背景 前阵子写一个项目时,有个需求是要往3个库,3个表里插入数据,在同一个方法里,公司是用baomidou的@DS注解来实现配置动态数据源的.这是背景,然后呢,我在一个service方法里,就操作了这三张表,同时,我还加上了@Transac

  • 解决SpringBoot中使用@Transactional注解遇到的问题

    目录 使用@Transactional注解遇到的问题 1.不建议在接口上添加@Transactional注解 2.@Transactional注解 3.默认情况下 4.数据库引擎需要支持事务管理 5.同一类中methodA()方法 springboot 注解transactional失效 1.在方法中捕获了异常 2.spring中事务是代理模式 3.A方法如果有事务注解 4.本类中A方法调用 使用@Transactional注解遇到的问题 1.不建议在接口上添加@Transactional注解

  • @Transactional注解不起作用的原因分析及解决

    目录 Transactional失效场景介绍 第一种 第二种 第三种 @Transactional注解不起作用原理分析 第一种 不创建代理对象 不进行代理调用 第二种 第三种 Transactional失效场景介绍 第一种 Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用.例如以下代码. 定义一个错误的@Transactional标注实现,修饰一个默认访问符的方法 /** * @author zhoujy * @date 2018年12

  • Spring事务注解@Transactional失效的八种场景分析

    首先说一下最近自己遇到的一个坑: @Transactional service A(){ try{ insert(); serviceB.update(); }catch(){ throw new RunTimeException(); } } serviceB(){ @Transactional update(){ try{ mapperB.update(); }catch(){ throw new RunTimeException(); } } } mapperB (){ try{ //do

  • 解决@Transactional注解事务不回滚不起作用的问题

    这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性 先来了解一下@Transactional注解事务的特性吧,可以更好排查问题 1.service类标签(一般不建议在接口上)上添加@Transactional,可以将整个类纳入spring事务管理,在每个业务方法执行时都会开启一个事务,不过这些事务采用相同的管理方式. 2.@Transactional 注解只能应用到 public 可

  • spring 中事务注解@Transactional与trycatch的使用

    spring事务注解@Transactional与trycatch 在项目中 @service层中 我们会经常在做一些增删改操作的方法上看到 spring 的事务注解 @transaction 已知@transaction 是让spring 帮我们实现事务的控制. 但是在项目中会经常看到 有的方法中 会存在trycatch块包括的方法上注解着@transaction eg: @Override @Transactional public Json addOrder(TOrderAddReq tO

  • @Transactional注解异常报错之多数据源详解

    目录 @Transactional注解报错之多数据源 1.在配置数据源的同时 2.一定要在需要使用事物注解的数据源配置里 @Transactional 错误使用的几种场景 @Transactional注解报错之多数据源 如果在加上@Transactional注解之后报错,先查看程序是否为多数据源,之前专门有一章讲解springboot的多数据源实现.多数据源的情况下加事物注解,有可能会出现问题,以下是解决方案. 1.在配置数据源的同时 一定到在其中一个配置上加上@Primary注解,其他的不要加

  • SQL注入报错注入函数图文详解

    目录 前言 常用报错函数 用法详解 updatexml()函数 实例 extractvalue()函数 floor()函数 exp()函数 12种报错注入函数 总结 前言 报错注入的前提是当语句发生错误时,错误信息被输出到前端.其漏洞原因是由于开发人员在开发程序时使用了print_r (),mysql_error(),mysqli_connect_error()函数将mysql错误信息输出到前端,因此可以通过闭合原先的语句,去执行后面的语句. 常用报错函数 updatexml()        

  • Python基础中所出现的异常报错总结

    今天我们来探索python中大部分的异常报错 首先异常是什么,异常白话解释就是不正常,程序里面一般是指程序员输入的格式不规范,或者需求的参数类型不对应,不全等等. 打个比方很多公司年终送苹果笔记本,你程序话思维以为是(MAC)电脑笔记本,结果给你个苹果+笔记本...首先类型不对,数量也不对. 先来看几个常见的报错如下: NameError 命名错误 原因是: name 'a' is not defined  命名a还未定义 简单来说就是程序不知道a带表谁 如果a=1 那程序就懂了 a代表1 所以

  • Spring Boot集成Druid出现异常报错的原因及解决

    Spring Boot集成Druid异常 在Spring Boot集成Druid项目中,发现错误日志中频繁的出现如下错误信息: discard long time none received connection. , jdbcUrl : jdbc:mysql://******?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8, version : 1.2.3, las

  • 类添加注解@RequestMapping报错HTTP Status 404的解决

    目录 类添加注解@RequestMapping报错HTTP Status 404 springMVC使用@RequestMapping遇到的问题 1.简介 2.属性简介 3.测试使用时遇到的问题 解决后的源码是 类添加注解@RequestMapping报错HTTP Status 404 为类添加了@RequestMapping注解后,运行报错404,路径不对,找了半天才发现原来是我的视图解析器的前缀没有写正确 在WEB-INF前面少加了一个/,加上之后运行ok springMVC使用@Reque

  • 导入maven项目各个注解均报错的解决方案

    目录 导入maven项目各个注解均报错 所遇问题 解决方案 新导入maven项目注解爆红,所有依赖包无法导入 经过反复测试终于发现原因所在!!! 解决步骤如下 导入maven项目各个注解均报错 所遇问题 导入maven项目各个注解均报错了 思考1: 这个项目使用了springboot;spring是个"大容器",所有对象的创建和管理都交给了它, (SpringBoot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,所谓简化是指简化了Spring众多框架中所需的大量且繁琐的配置

  • Python如何处理异常报错方法(建议收藏!)

    目录 写在前面 什么是异常? 如何处理异常? try 与 except 用法 例子 python标准异常 写在最后 写在前面 今天Python笔记的内容是: 异常处理 一旦Python脚本发生异常,程序需捕获并处理异常. 异常处理使得程序能够在处理异常后继续正常执行,不至于崩溃或终止执行. 什么是异常? 当Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误. 当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行 举个例子: >>> a =

  • Mybatis-Plus进阶分页与乐观锁插件及通用枚举和多数据源详解

    分页插件   MP中自带了分页插件的功能,只需要在配置类中进行简单的配置即可使用分页的相关功能.分页插件常常与前端的分页显示功能相关,为了在前端美观的显示查询到的数据,通常会使用分页插件,将所有的数据分成许多页一页一页的进行显示,不同页的切换使用按钮来完成 MP的插件配置类 @Configuration public class MybatisPlusConfiguration { @Bean public MybatisPlusInterceptor mybatisPlusIntercepto

  • Java 异常的栈轨迹(Stack Trace)详解及实例代码

    Java 异常的栈轨迹(Stack Trace)详解 捕获到异常时,往往需要进行一些处理.比较简单直接的方式就是打印异常栈轨迹Stack Trace.说起栈轨迹,可能很多人和我一样,第一反应就是printStackTrace()方法.其实除了这个方法,还有一些别的内容也是和栈轨迹有关的. 1.printStackTrace() 首先需要明确,这个方法并不是来自于Exception类.Exception类本身除了定义了几个构造器之外,所有的方法都是从其父类继承过来的.而和异常相关的方法都是从jav

  • Laravel 修改验证异常的响应格式实例代码详解

    Laravel 默认验证不通过后响应格式如下,有时此格式并不满足自己要求,需要修改格式. // status 422 { "message":"The given data was invalid.", "errors":{ "url":[ "url 无效的格式" ] } } 当 Request 验证失败时会抛出 ValidationException异常,最终交由全局异常Handler类处理.Handle

随机推荐