7、springboot多模块多数据源全局事务的设置

1、绑定第一个数据库

/**
 * 创建多数据源的过程就是:首先创建 DataSource,
 * 注入到 SqlSessionFactory 中,再创建事务,
 * 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中,
 * 最后将 SqlSessionTemplate 注入到对应的 Mapper 包路径下。
 * 其中需要指定分库的 Mapper 包路径。
 */
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.test.datasource1",sqlSessionTemplateRef = "sqlSessionTemplate1")
public class DataSourceConfig1 {

    /**
     * 创建 DataSource
     * @return
     */
    @Bean(name="dataSource1")
    //配置文件中数据库的参数
    @ConfigurationProperties(prefix = "spring.datasource.hikari.data1")
    public DataSource dataSource(){
        return DataSourceBuilder.create().build();
    }

    /**
     * 注入到 SqlSessionFactory 中
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean(name = "sqlSessionFactory1")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource1") DataSource dataSource) throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/test/dao/mapper/dao1/*.xml"));
        return bean.getObject();
    }
     //配置事务
    @Bean(name = "transactionManagerTest1")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource1") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中
     * @param sqlSessionFactory
     * @return
     */
    @Bean(name="sqlSessionTemplate1")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }
    //配置事务
    //注意这个bean名transactionManager1,将在TxAdviceInterceptor文件中使用
    @Bean
    public PlatformTransactionManager transactionManager1(@Qualifier("dataSource1") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

2、绑定第二个数据库

/**
 * 创建多数据源的过程就是:首先创建 DataSource,
 * 注入到 SqlSessionFactory 中,再创建事务,
 * 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中,
 * 最后将 SqlSessionTemplate 注入到对应的 Mapper 包路径下。
 * 其中需要指定分库的 Mapper 包路径。
 */
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.test.datasource2",sqlSessionTemplateRef = "sqlSessionTemplate2")
public class DataSourceConfig2 {

    /**
     * 创建 DataSource
     * @return
     */
    @Bean(name="dataSource2")
    //配置文件中数据库的参数
    @ConfigurationProperties(prefix = "spring.datasource.hikari.data2")
    public DataSource dataSource(){
        return DataSourceBuilder.create().build();
    }

    /**
     * 注入到 SqlSessionFactory 中
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean(name = "sqlSessionFactory2")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource2") DataSource dataSource) throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/test/dao/mapper/dao2/*.xml"));
        return bean.getObject();
    }
     //配置事务
    @Bean(name = "transactionManagerTest2")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource2") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中
     * @param sqlSessionFactory
     * @return
     */
    @Bean(name="sqlSessionTemplate2")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }
    //配置事务
    //注意这个bean名transactionManager2
    @Bean
    public PlatformTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

3、application-dev.yml配置文件

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      mdm:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: 123456
		connection-timeout: 30000
        idle-timeout: 600000
        max-lifetime: 620000
        maximum-pool-size: 30
        minimum-idle: 5
		pool-name: DatebookHikariCP
	  msg:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: 123456
        connection-timeout: 30000
        idle-timeout: 600000
        max-lifetime: 620000
        maximum-pool-size: 30
        minimum-idle: 5
        pool-name: DatebookHikariCP

4、配置全局事务

@Aspect
@Configuration
public class TxAdviceInterceptor {
    private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.test.service.impl.*.*(..))";
    @Autowired
    private PlatformTransactionManager transactionManager1;//刚才设置的bean

    @Bean
    public TransactionInterceptor txAdvice() {
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        /* 当前没有事务:只有select,非事务执行;有update,insert,delete操作,自动提交;
         * 当前有事务:如果有update,insert,delete操作,支持当前事务 */
        /*只读事务,不做更新操作*/
        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
        /* 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务 */
        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // requiredTx.setTimeout(TX_METHOD_TIMEOUT);
        Map<String, TransactionAttribute> txMap = new HashMap<>();
        txMap.put("get*", readOnlyTx);
        txMap.put("*", requiredTx);
        source.setNameMap(txMap);
        TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager1, source);
        return txAdvice;
    }

    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}

5、springboot启动文件

//war部署到tomcat
@EnableAsync
@EnableTransactionManagement//开启事务
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableScheduling
@MapperScan({"com.test.dao.persistence"})
public class AdminApplication extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(AdminApplication.class);
    }


    //返回设置为utf-8
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        return converter;
    }
}

注意:

只能在一个数据源上配置全局事务。不使用TxAdviceInterceptor文件的话,还可以在service文件上或者service方法上使用注解

@Transactional(transactionManager = "transactionManager1"),注解上必须标明是使用哪个事务

这样就会对相关service文件中报错了,设计到第一个数据源的就会回滚

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值