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

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

一.引入相应的maven依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.0.5</version>
</dependency>

二.配置数据源

 1.这里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

2.分包配置数据源

3.注入第一个数据源

/**
 * @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);
    }

4.注入第二个数据源

/**
 * @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);
    }

5.注入第三个数据源

/**
 * @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

猜你喜欢

转载自blog.csdn.net/qq_35859844/article/details/88577584
今日推荐