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

 更新时间:2022年01月25日 11:53:20   作者:wuyuanshun  
这篇文章主要介绍了@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;
}

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

相关文章

  • Shiro与Springboot整合开发的基本步骤过程详解

    Shiro与Springboot整合开发的基本步骤过程详解

    这篇文章主要介绍了Shiro与Springboot整合开发的基本步骤,本文结合实例代码给大家介绍整合过程,感兴趣的朋友跟随小编一起看看吧
    2023-06-06
  • spring mvc路径匹配原则详解

    spring mvc路径匹配原则详解

    这篇文章主要介绍了spring mvc路径匹配原则详解,小编觉得还是挺不错的,这里分享给大家,需要的朋友可以参考下,下面就和小编一起来看看吧
    2018-02-02
  • Spring Cloud gateway 网关如何拦截Post请求日志

    Spring Cloud gateway 网关如何拦截Post请求日志

    这篇文章主要介绍了Spring Cloud gateway 网关如何拦截Post请求日志的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • SpringBoot使用thymeleaf实现前端表格

    SpringBoot使用thymeleaf实现前端表格

    虽然现在流行前后端分离,但是后端模版在一些关键地方还是非常有用的,例如邮件模版、代码模版等。当然也不排除一些古老的项目后端依然使用动态模版。Thymeleaf 简洁漂亮、容易理解,并且完美支持 HTML5,可以直接打开静态页面,同时不新增标签,只需增强属性
    2022-10-10
  • IDEA中的HTTP Client使用教程

    IDEA中的HTTP Client使用教程

    这篇文章主要介绍了IDEA中的HTTP Client使用教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Springboot启动不检查JPA的数据源配置方式

    Springboot启动不检查JPA的数据源配置方式

    这篇文章主要介绍了Springboot启动不检查JPA的数据源配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • mybatis整合ehcache做三级缓存的实现方法

    mybatis整合ehcache做三级缓存的实现方法

    ehcache是一个快速内存缓存框架,java项目里用起来很方便,下面这篇文章主要给大家介绍了关于mybatis整合ehcache做三级缓存的实现方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • 详解SpringBoot整合MyBatis详细教程

    详解SpringBoot整合MyBatis详细教程

    这篇文章主要介绍了详解SpringBoot整合MyBatis详细教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Java实现简单的学生教师管理系统

    Java实现简单的学生教师管理系统

    这篇文章主要为大家详细介绍了Java实现简单的学生教师管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • Intellij IDEA中如何查看maven项目中所有jar包的依赖关系图

    Intellij IDEA中如何查看maven项目中所有jar包的依赖关系图

    这篇文章主要介绍了Intellij IDEA中如何查看maven项目中所有jar包的依赖关系图,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05

最新评论