一、配置perproties/yml文件
(1)不同數據庫的配置信息
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.tomcat= com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/paidan_data_upload?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=300000
#spring.datasource.slave.poolName=slave
spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.slave.url=jdbc:mysql://localhost:3306/paidan_data_upload2?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
spring.datasource.slave.username=root
spring.datasource.slave.password=123456
spring.datasource.slave.hikari.minimum-idle=5
spring.datasource.slave.hikari.maximum-pool-size=15
spring.datasource.slave.hikari.auto-commit=true
spring.datasource.slave.hikari.idle-timeout=300000
spring.datasource.slave.hikari.pool-name=DatebookHikariCP
spring.datasource.slave.hikari.max-lifetime=1800000
spring.datasource.slave.hikari.connection-timeout=300000
mybatis-plus.mapper-locations=classpath:/mapper/*Mapper.xml
#實體掃描,多個package用逗號或者分號分隔
mybatis-plus.typeAliasesPackage=com.chinadep.*.dataroute.bean,com.chinadep.*.mapper
mybatis-plus.global-config.id-type=3
mybatis-plus.global-config.field-strategy=2
mybatis-plus.global-config.db-column-underline=true
mybatis-plus.global-config.capital-mode=true
mybatis-plus.configuration.lazy-loading-enabled=false
mybatis-plus.configuration.aggressive-lazy-loading=false
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.configuration.cache-enabled=false
mybatis-plus.configuration.jdbc-type-for-null=null
二、一些配置文件
(1)DatabaseType(不同數據庫的名字標誌(可以任意填寫))
public enum DatabaseType {
dataBase1,
dataBase2
}
(2)DynamicDataSource(動態數據源(需要繼承AbstractRoutingDataSource))
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
//使用DatabaseContextHolder獲取當前線程的DatabaseType
return DatabaseContextHolder.getDatabaseType();
}
}
(3)DatabaseContextHolder(保存一個線程安全的DatabaseType容器)
public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();
public static void setDatabaseType(DatabaseType type) {
contextHolder.set(type);
}
public static DatabaseType getDatabaseType() {
return contextHolder.get();
}
}
(4)Mybatisplus配置
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor page = new PaginationInterceptor();
//設置方言
page.setDialectType("mysql");
return page;
}
/**
* sql性能分析插件
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor().setFormat(false);
}
/**
* 執行分析插件
*/
@Bean
public SqlExplainInterceptor sqlExplainInterceptor() {
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
sqlExplainInterceptor.setStopProceed(false);
return sqlExplainInterceptor;
}
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* Primary 該註解表示在同一個接口有多個實現類可以注入的時候,默認選擇哪一個,而不是讓@autowire註解報錯
* Qualifier 根據名稱進行注入,通常是在具有相同的多個類型的實例的一個注入(例如有多個DataSource類型的實例)
*/
@Bean
@Primary
public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
@Qualifier("slaveDataSource") DataSource slaveDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DatabaseType.dataBase1, masterDataSource);
targetDataSources.put(DatabaseType.dataBase2, slaveDataSource);
DynamicDataSource dataSource = new DynamicDataSource();
// 該方法是AbstractRoutingDataSource的方法
dataSource.setTargetDataSources(targetDataSources);
// 默認的datasource設置爲myTestDbDataSource
dataSource.setDefaultTargetDataSource(masterDataSource);
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource,
@Qualifier("slaveDataSource") DataSource slaveDataSource) throws Exception {
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean =new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(this.dataSource(masterDataSource, slaveDataSource));
return mybatisSqlSessionFactoryBean.getObject();
}
/**
* 配置事務管理器
*/
@Bean
public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
return new DataSourceTransactionManager(dataSource);
}
}
(5)使用
@GetMapping(value = "/test")
public void saveTestServerUrl() {
List<ServerUrl> serverUrlRestult = serverUrlDao.selectList(new EntityWrapper<>());
System.out.println(serverUrlRestult);
DatabaseContextHolder.setDatabaseType(DatabaseType.dataBase2);
List<ServerUrl> serverUrlRestult1 = serverUrlDao.selectList(new EntityWrapper<>());
System.out.println(serverUrlRestult1);
}
三、注意(踩坑)
(1)之前按照整合mybatis多數據源的方式去整合mybatisplus,項目正常啓動,但是當請求db的時候,出現org.apache.ibatis.binding.BindingException: Invalid bound statement not found 錯誤。當時想的是mybatisplus和mybatis是向下兼容的,配置的方式應該是一樣的。然後事實並非如此,出現這個問題之後,就猜想是不是缺少哪些配置,導致mybatisplus掃描不到自己封裝的xml文件(調用的是plus自帶的方法,沒有自定義xml文件)。之後嘗試過各種mapperscan,無濟於事。。。。
先說明,原理還沒搞懂。大概原因是,MybatisPlus需要用自己的 MybatisSqlSessionFactoryBean,用SqlSessionFactory 可能有問題。
(2)解決方案:
將mybatisplus配置sqlSessionFactory改成MybatisSqlSessionFactoryBean。問題解決
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean =new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(this.dataSource(masterDataSource, slaveDataSource));