Springboot多数据源切换

Springboot-DynamicData

springboot 多个数据源的配置
解决问题, 一个springboot 项目操作多个数据库的数据

新建springboot项目 添加pom依赖

      <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>

新建 config 包添加配置项

  • 新建枚举类多个数据源
public enum DatabaseTypeEnum {
    PRIMARY("1"), USER("2");

    private String code;

    DatabaseTypeEnum(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public static DatabaseTypeEnum getDatabaseTypeEnum(String code) {
        for (DatabaseTypeEnum databaseTypeEnum : DatabaseTypeEnum.values()) {
            if (databaseTypeEnum.getCode().equals(code)) {
                return databaseTypeEnum;
            }
        }
        return null;
    }
}
  • 新建 HikariConfig 类,添加数据源配置
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author yyb
 * @time 2019/3/27
 */
@Service
public class HikariConfig {
    @Value("${spring.datasource.username}")
    private String userName;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.min-idle}")
    private Integer minIdle;
    @Value("${spring.datasource.max-active}")
    private Integer maxActive;
    @Value("${spring.datasource.validation-query}")
    private String validationQuery;
    @Value("${spring.datasource.connection-timeout}")
    private Integer connectionTimeout;
    @Value("${spring.datasource.max-left-time}")
    private Integer maxLeftTime;
    @Value("${spring.datasource.validation-time-out}")
    private Integer validationTimeout;
    @Value("${spring.datasource.idle-time-out}")
    private Integer idleTimeout;
    @Value("${spring.datasource.connection-init-sql}")
    private String connectionInitSql;

    /**
     * 配置Hikari数据连接池
     *
     * @param url 数据源
     * @return 连接池对象
     */
    public HikariDataSource getHikariDataSource(String url) {
        com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig();
        config.setMinimumIdle(minIdle);
        config.setMaximumPoolSize(maxActive);
        config.setConnectionTestQuery(validationQuery);
        config.setJdbcUrl(url);
        config.setUsername(userName);
        config.setPassword(password);
        config.setDriverClassName(driverClassName);
        config.setConnectionTimeout(connectionTimeout);
        config.setMaxLifetime(maxLeftTime);
        config.setValidationTimeout(validationTimeout);
        config.setConnectionInitSql(connectionInitSql);
        return new HikariDataSource(config);
    }

    /**
     * 用于两个库账号密码不一样的时候
     *
     * @param url
     * @param userName
     * @param passwod
     * @return
     */
    public HikariDataSource getHikariDataSource(String url, String userName, String passwod) {
        com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig();
        config.setMinimumIdle(minIdle);
        config.setMaximumPoolSize(maxActive);
        config.setConnectionTestQuery(validationQuery);
        config.setJdbcUrl(url);
        config.setUsername(userName);
        config.setPassword(passwod);
        config.setConnectionTimeout(connectionTimeout);
        config.setDriverClassName(driverClassName);
        config.setMaxLifetime(maxLeftTime);
        config.setValidationTimeout(validationTimeout);
        config.setConnectionInitSql(connectionInitSql);
        return new HikariDataSource(config);
    }
  • 新建DynamicDataSourceConfig 类配置两个数据源
import cn.abel.enums.DatabaseTypeEnum;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
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 javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yyb
 * @time 2019/3/27
 */
@Configuration
@MapperScan(basePackages = "cn.abel.dao")
public class DynamicDataSourceConfig {
    @Value("${spring.datasource.primary.url}")
    private String primaryUrl;
    @Value("${spring.datasource.user.url}")
    private String userUrl;
    @Value("${mybatis.mapper-locations}")
    private String resources;
    //当两个数据库连接账号密码不一样时
//    @Value("${spring.datasource.user.username}")
//    private String userName;
//    @Value("${spring.datasource.user.password}")
//    private String password;

    @Autowired
    private HikariConfig hikariConfig;

    @Primary
    @Bean(name = "primaryDataSource")
    public DataSource getPrimaryDataSource() {
        return hikariConfig.getHikariDataSource(primaryUrl);
    }

    @Bean(name = "userDataSource")
    public DataSource getUserDataSource() {
        return hikariConfig.getHikariDataSource(userUrl);
    }


    //当两个数据库连接账号密码不一样时使用
//    @Bean(name = "userDataSource")
//    public DataSource getUserDataSource() {
//        return hikariConfig.getHikariDataSource(userUrl, userName, password);
//    }


    @Bean("dynamicDataSource")
    public DynamicDataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
                                               @Qualifier("userDataSource") DataSource miaoMoreDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseTypeEnum.PRIMARY, primaryDataSource);
        targetDataSources.put(DatabaseTypeEnum.USER, miaoMoreDataSource);

        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
        dataSource.setDefaultTargetDataSource(primaryDataSource);// 默认的datasource设置为myTestDbDataSource
        return dataSource;
    }

    /**
     * 根据数据源创建SqlSessionFactory
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dynamicDataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(resources));
        return bean.getObject();
    }
}
  • 新建 DynamicDataSourceContextHolder 数据源切换路由
import cn.abel.enums.DatabaseTypeEnum;

/**
 * @author yyb
 * @time 2019/3/27
 */
public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<DatabaseTypeEnum> contextHolder = new ThreadLocal<>();

    public static void setDatabaseType(DatabaseTypeEnum type){
        contextHolder.set(type);
    }

    public static DatabaseTypeEnum getDatabaseType(){
        return contextHolder.get();
    }

    public static void resetDatabaseType() {
        contextHolder.set(DatabaseTypeEnum.PRIMARY);
    }
}

  • 新建 DynamicDataSource 动态数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @author yyb
 * @time 2019/3/27
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDatabaseType();
    }
}

使用

在service 层调用dao 层的时候,进行数据源切换操作


    public List<News> getByMap(Map<String, Object> map) {
        //重置数据源,切换为默认数据源
        DynamicDataSourceContextHolder.resetDatabaseType();
        return newsDao.getByMap(map);
    }

在需要的地方切换第二个数据源


  	public User getById(Integer id){
		 //切换为配置第二数据源
		 
DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER);
		return userDao.getById(id);
	}

完整代码:https://github.com/527515025/springBoot/tree/master/springboot-dynamicDataSource

发布了343 篇原创文章 · 获赞 649 · 访问量 231万+

猜你喜欢

转载自blog.csdn.net/u012373815/article/details/89296341