栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

解决SpringBoot项目多数据源事务回滚失败的问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解决SpringBoot项目多数据源事务回滚失败的问题

项目中配置了两种数据源,一种是hana, 一种是mysql

场景:

在方法中,使用了hana数据源从hana数据库中查出数据,然后将数据写到mysql数据库中,对数据库进行修改操作时,我们一般会添加事务回滚的操作,以便程序出错时可以还原数据库。

问题:

在方法中添加能使程序异常的代码(比如:int i = 1/0;)进行测试,并在方法中贴上以下注解:

@Transactional(rollbackFor = Exception.class)

但是发现事务并没有回滚 

检查了项目的配置, 两个数据源配置了事务管理器:

hana数据源配置:

import javax.sql.DataSource;

import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.jdbc.DataSourceBuilder;
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.DataSourceTransactionManager;
import top.ibase4j.core.Constants;
import top.ibase4j.core.util.PropertiesUtil;
import top.ibase4j.core.util.SecurityUtil;
@Configuration
@MapperScan(basePackages = "com.xxx.mapper.hana",sqlSessionTemplateRef ="hanaSqlSessionTemplate")
public class HanaDataSourceConfig {

    
	@Bean(name = "hanaDataSource")
	@Primary
	public DataSource gethanaDataSource() {
		DataSource build =  DataSourceBuilder.create()
				
				.driverClassName(PropertiesUtil.getString("hana.driverClassName"))
				.url(PropertiesUtil.getString("hana.url"))
				.username(PropertiesUtil.getString("hana.username"))
				.password(SecurityUtil.decryptDes(PropertiesUtil.getString("hana.password"), Constants.DB_KEY.getBytes()))
				.build();
		return build;
    }
    
    @Bean(name = "hanaSqlSessionFactory")
	@Primary
	public SqlSessionFactory hanaSqlSessionFactory(@Qualifier("hanaDataSource") DataSource dataSource) throws Exception {
		MybatisSqlSessionFactoryBean  bean = new MybatisSqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		//设置mapper配置文件
		bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/hana
	@Bean("hanaTransactionManger")
	@Primary
	public DataSourceTransactionManager hanaTransactionManger(@Qualifier("hanaDataSource") DataSource dataSource){
		return new DataSourceTransactionManager(dataSource);
	}

	
	@Bean(name = "hanaSqlSessionTemplate")
	@Primary
	public SqlSessionTemplate hanaSqlSessionTemplate(@Qualifier("hanaSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
		return new SqlSessionTemplate(sqlSessionFactory);
	}
    
}

mysql数据源配置:

import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import top.ibase4j.core.util.PropertiesUtil;

import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.xxx.mapper.mysql",sqlSessionTemplateRef ="mysqlSqlSessionTemplate")
public class MysqlDataSourceConfig {

	@Resource
	private MybatisPlusConfig mybatisPlusConfig;

    
	@Bean(name = "mysqlDataSource")
	public DataSource getmysqlDataSource() {
		DataSource build =  DataSourceBuilder.create()
				.driverClassName(PropertiesUtil.getString("druid.default.driverClassName"))
				.url(PropertiesUtil.getString("druid.writer.default.url"))
				.username(PropertiesUtil.getString("druid.writer.default.username"))
				.password(PropertiesUtil.getString("druid.writer.default.password"))
				.build();
		return build;
 	   }

    @Bean(name = "mysqlSqlSessionFactory")
	public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception {
		MybatisSqlSessionFactoryBean  bean = new MybatisSqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		//设置mapper配置文件
		bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/mysql
	@Bean("mysqlTransactionManger")
	public DataSourceTransactionManager mysqlTransactionManger(@Qualifier("mysqlDataSource") DataSource dataSource){
		return new DataSourceTransactionManager(dataSource);
	}

	
	@Bean(name = "mysqlSqlSessionTemplate")
	public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
		return new SqlSessionTemplate(sqlSessionFactory);
	}


}

由于默认的数据源是hana数据源,但是现在我们要将mysql的事务进行回滚,如果不将默认的事务管理器设置mysql对应的事务管理器为默认的话, 事务回滚将不起作用。

 因此,可以添加配置类,以配置默认的事务管理器为mysql的,配置类要实现TransactionManagementConfigurer

@Configuration
public class SpecifyDefaultTransactionManagerConfig implements TransactionManagementConfigurer {
    @Autowired
    private MysqlDataSourceConfig mysqlDataSourceConfig;
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return mysqlDataSourceConfig.mysqlTransactionManger(mysqlDataSourceConfig.getmysqlDataSource());
    }

再次进行测试,事务将回滚成功

如果不想添加配置类,可以在注解中标明使用的是哪个事务管理器

这里我们要用的是mysql的,因此可以这样配置

@Transactional(value = "mysqlTransactionManger",rollbackFor = Exception.class)

value的值就是事务管理器bean的名称

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/946213.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号