SpringBoot配置多数据源
在application配置文件中添加两个数据源的url,username,password和DriverName。
一、DatabaseContextHolder
/**
* @program:
* @description: 保存一个线程安全的DatabaseType容器
* @author:
* @create: 2019-04-26 16:14
**/
public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();
/**
* 默认使用的是portfolio库,如果要使用auth库需要在dao.select()方法上加此方法并设置对应库
* @param type
*/
public static void setDatabaseType(DatabaseType type){
contextHolder.set(type);
}
public static DatabaseType getDatabaseType(){
return contextHolder.get();
}
二、DatabaseType枚举(枚举名称一般对应数据库名称)
/**
* 数据库类型(数据库名称)
* @author
*/
public enum DatabaseType {
sandbox_merak_auth_zjrc,sandbox_portfolio_v3_zjrc;
}
三、DataSourceConfig(主要配置)
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.pivot.squirrelsave.common.core.util.PropertiesUtil;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
/**
* springboot集成mybatis的基本入口
* 1)创建数据源(如果采用的是默认的tomcat-jdbc数据源,则不需要
* 2) 创建SqlSessionFactory
* 3)配置事务管理器,除非需要使用事务,否则不用配置
*
* @author
*/
@Configuration
@MapperScan(basePackages = "*.**.mapper")
public class DataSourceConfig {
@Autowired
private Environment env;
/**
* 创建数据源(数据源的名称:方法名可以取为XXXDataSource(),XXX为数据库名称,该名称也就是数据源的名称)
*/
@Bean("sandbox_portfolio_v3_zjrc")
public DataSource myTestDbDataSource() throws Exception {
Properties props = new Properties();
props.put("driverClassName", PropertiesUtil.getString("druid.driverClassName"));
props.put("url", PropertiesUtil.getString("druid.writer.url"));
props.put("username", PropertiesUtil.getString("druid.writer.username"));
props.put("password", PropertiesUtil.getString("druid.writer.password"));
return DruidDataSourceFactory.createDataSource(props);
}
@Bean("sandbox_merak_auth_zjrc")
public DataSource myTestDb2DataSource() throws Exception {
Properties props = new Properties();
props.put("driverClassName", PropertiesUtil.getString("druid.driverClassName"));
props.put("url", PropertiesUtil.getString("druid.writer.url.auth"));
props.put("username", PropertiesUtil.getString("druid.writer.username.auth"));
props.put("password", PropertiesUtil.getString("druid.writer.password.auth"));
return DruidDataSourceFactory.createDataSource(props);
}
/**
* @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@autowire注解报错
* @Qualifier 根据名称进行注入,通常是在具有相同的多个类型的实例的一个注入(例如有多个DataSource类型的实例)
*/
@Bean("double")
@Primary
public DynamicDataSource dynamicDataSource(@Qualifier("sandbox_portfolio_v3_zjrc") DataSource portfolio,
@Qualifier("sandbox_merak_auth_zjrc") DataSource auth) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DatabaseType.sandbox_portfolio_v3_zjrc, portfolio);
targetDataSources.put(DatabaseType.sandbox_merak_auth_zjrc, auth);
DynamicDataSource dataSource = new DynamicDataSource();
// 该方法是AbstractRoutingDataSource的方法
dataSource.setTargetDataSources(targetDataSources);
// 默认的datasource设置为portfolio
dataSource.setDefaultTargetDataSource(portfolio);
return dataSource;
}
/**
* 根据数据源创建SqlSessionFactory
*/
@Bean("doubleSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("sandbox_portfolio_v3_zjrc") DataSource portfolio,
@Qualifier("sandbox_merak_auth_zjrc") DataSource auth) throws Exception {
MybatisSqlSessionFactoryBean fb = new MybatisSqlSessionFactoryBean();
// 指定数据源(这个必须有,否则报错)
fb.setDataSource(this.dynamicDataSource(portfolio,auth));
// 下边两句仅仅用于*.xml文件,如果整个持久层操作不需要使用到xml文件的话(只用注解就可以搞定),则不加
// 指定基包
fb.setTypeAliasesPackage(PropertiesUtil.getString("mybatis.typeAliasesPackage"));
fb.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources(PropertiesUtil.getString("mybatis.mapperLocations")));
//枚举所在包
fb.setTypeHandlersPackage(PropertiesUtil.getString("type-handlers-package"));
fb.setTypeEnumsPackage(PropertiesUtil.getString("mybatis.locationConfig"));
return fb.getObject();
}
/**
* 配置事务管理器
*/
@Bean("doubleTransactionManager")
public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
四、DynamicDataSource(动态切换数据源)
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @program:
* @description: 动态数据源(需要继承AbstractRoutingDataSource)
* @author:
* @create: 2019-04-26 16:21
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
======================================================================
这里默认用的portfolio库,所以如果当你要用另一个库(auth)进行查询时,要在dao调用方法的上一行添加DatabaseContextHolder.setDatabaseType(DatabaseType.sandbox_merak_auth_zjrc);
它会自动帮你切换到另一个库。
具体操作可以debug尝试一下这行代码。
注:亲测可用。代码中我用的自定义获取properties中属性的工具。如果你定义在application.properties的话可以在DataSourceConfig类中@Autowired注入Environment。然后env.getProperty(“属性名”);就能取到值了
参考链接:https://www.cnblogs.com/java-zhao/p/5413845.html