springboot+分包,实现多数据源切换和事务管理(靠谱版)

说明:之前写的这篇springboot+aop+自定义注解,实现多数据源切换(通用版)经过测试有些发现事务无法管理,有时候切换数据源容易失败,现在用一种更靠谱的方式来实现多数据源切换。

一.引入相应的maven依赖


	org.springframework.boot
	spring-boot-starter-web


	org.projectlombok
	lombok
	true


	mysql
	mysql-connector-java


	com.alibaba
	druid
	1.0.5

二.配置数据源

  • 这里application.properties配置了三个数据源
spring.datasource.user.url = jdbc:mysql://10.237.150.79:3306/user?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
spring.datasource.user.username = root
spring.datasource.user.password = root
spring.datasource.user.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.user.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.user.filters = stat
spring.datasource.user.maxActive = 100
spring.datasource.user.initialSize = 10
spring.datasource.user.maxWait = 60000
spring.datasource.user.minIdle = 500

spring.datasource.china.url = jdbc:mysql://10.237.150.79:3306/china?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
spring.datasource.china.username = root
spring.datasource.china.password = root
spring.datasource.china.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.china.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.china.filters = stat
spring.datasource.china.maxActive = 100
spring.datasource.china.initialSize = 10
spring.datasource.china.maxWait = 60000
spring.datasource.china.minIdle = 500

spring.datasource.world.url = jdbc:mysql://10.237.150.79:3306/world?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
spring.datasource.world.username = root
spring.datasource.world.password = root
spring.datasource.world.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.world.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.world.filters = stat
spring.datasource.world.maxActive = 100
spring.datasource.world.initialSize = 10
spring.datasource.world.maxWait = 60000
spring.datasource.world.minIdle = 500

  • 分包配置数据源

springboot+分包,实现多数据源切换和事务管理(靠谱版)_第1张图片

  • 注入第一个数据源
/**
 * @Author: guandezhi
 * @Date: 2019/3/14 21:06
 */
@Configuration
@MapperScan(basePackages = {"com.gdz.dynamic.mapper.china"}, sqlSessionTemplateRef  = "chinaSqlSessionTemplate")
public class ChinaDataSourceConfig {

    @Bean(name = "chinaDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.china")
    public DataSource chinaDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "chinaSqlSessionFactory")
    @Primary
    public SqlSessionFactory chinaSqlSessionFactory(@Qualifier("chinaDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/china/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "chinaTransactionManager")
    @Primary
    public DataSourceTransactionManager chinaTransactionManager(@Qualifier("chinaDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "chinaSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate chinaSqlSessionTemplate(@Qualifier("chinaSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
  • 注入第二个数据源
/**
 * @Author: guandezhi
 * @Date: 2019/3/14 21:06
 */
@Configuration
@MapperScan(basePackages = {"com.gdz.dynamic.mapper.user"}, sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataSourceConfig {

    @Bean(name = "userDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.user")
    public DataSource userDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "userSqlSessionFactory")
    public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/user/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "userTransactionManager")
    public DataSourceTransactionManager userTransactionManager(@Qualifier("userDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "userSqlSessionTemplate")
    public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
  • 注入第三个数据源
/**
 * @Author: guandezhi
 * @Date: 2019/3/14 21:06
 */
@Configuration
@MapperScan(basePackages = {"com.gdz.dynamic.mapper.world"}, sqlSessionTemplateRef  = "worldSqlSessionTemplate")
public class WorldDataSourceConfig {

    @Bean(name = "worldDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.world")
    public DataSource worldDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "worldSqlSessionFactory")
    public SqlSessionFactory worldSqlSessionFactory(@Qualifier("worldDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/world/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "worldTransactionManager")
    public DataSourceTransactionManager worldTransactionManager(@Qualifier("worldDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "worldSqlSessionTemplate")
    public SqlSessionTemplate worldSqlSessionTemplate(@Qualifier("worldSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

这样就已经可以实现多数据源的切换了。

总结:

         1.事务的使用必须要指明是哪个数据源的事务管理器,否则事务失效

            例如:@Transactional(value = "userTransactionManager")

         2.如果一个方法涉及多个数据源操作,此时无法做到同时回滚,尽量避免这种操作,

           这里涉及到分布式事务处理,可自行研究。

代码地址:https://github.com/dezhiguan/DynamicDataSource2/tree/master

你可能感兴趣的:(springboot)