最近在學習spring boot,發如今jar包依賴方面作不多的工做量就能夠了,對於數據庫操做,我用的比較多的是mybatis plus,在中央倉庫已經有mybatis-plus的插件了,對於單數據源來講直接使用就是了,但我本身的項目常常會有多數據源的狀況,本身去試着寫數據源的代碼,核心的方法參考mp說明文檔中多數據源的處理,使用動態數據源,根據需求去切換數據源java
這一步你們去參考其它教程,很簡單mysql
繼承了抽像的數據源,並實現了DataSource,歸根結底仍是數據就是了,在這裏面進行擴展,實現determiniCurrentlookupKey,也就是獲取當前須要使用數據源的key值,在父類方法中有一個map,用來保存key值與數據源的對應關係,而key值是與當前線程相關的,DbcontextHolder代碼見下spring
package com.zhangshuo.common.dataSource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * Created by Administrator on 2017/5/31 0031. */ publicclassDynamicDataSourceextendsAbstractRoutingDataSource{ /** * 取得當前使用哪一個數據源 * * @return */ @Override protectedObject determineCurrentLookupKey(){ returnDbContextHolder.getDbType(); } }
裏面包含靜態方法,用來設置或獲取線程相關的數據源別名sql
publicclassDbContextHolder{ privatestaticfinalThreadLocal<String> contextHolder =newThreadLocal<>(); /** * 設置數據源 * * @param dbTypeEnum */ publicstaticvoid setDbType(DBTypeEnum dbTypeEnum){ contextHolder.set(dbTypeEnum.getValue()); } /** * 取得當前數據源 * * @return */ publicstaticString getDbType(){ return contextHolder.get(); } /** * 清除上下文數據 */ publicstaticvoid clearDbType(){ contextHolder.remove(); } }
簡化設置線程相關數據源名稱的記憶壓力;直接從全部的數據源的枚舉中去選就能夠了~數據庫
publicenumDBTypeEnum{ datasource1("datasource1"), datasource2("datasource2"); privateString value; DBTypeEnum(String value){ this.value = value; } publicString getValue(){ return value; } }
在這裏定義的屬性名要與DruidDataSource和 SqlSessionFactory中須要的屬性相同,使用ConfigurationProperties註解來減小代碼apache
datasource1: username: root password: 123456 filters: mergeStat,wall,logback initialSize: 5 maxActive: 50 minIdle: 5 maxWait: 6000 validationQuery: SELECT 'x' testOnBorrow: true testOnReturn: true testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 removeAbandoned: true removeAbandonedTimeout: 1800 logAbandoned: true url: jdbc:mysql://192.168.168.118:3306/test?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&useSSL=false mybatis-plus1: # 數據源名稱 datasource: datasource1 # mapper配置路徑 mapperLocations: classpath:/mapper/test1/*.xml # mybatis配置路徑 configLocation: classpath:/mybatis-config.xml # entity的包 typeAliasesPackage: com.zhangshuo/test1/entity # 全局配置 globalConfiguration: # id生成策略 0 自增 1 用戶輸入 idType: 0 # 靈據數類型 dbType: mysql # 字段是否爲下劃線格式 dbColumnUnderline: false datasource2: username: root password: 123456 filters: mergeStat,wall,logback initialSize: 5 maxActive: 50 minIdle: 5 maxWait: 6000 validationQuery: SELECT 'x' testOnBorrow: true testOnReturn: true testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 removeAbandoned: true removeAbandonedTimeout: 1800 logAbandoned: true url: jdbc:mysql://192.168.168.118:3306/sms?useUnicode=true&characterEncoding=utf-8 mybatis-plus2: # 數據源名稱 datasource: datasource2 # mapper配置路徑 mapperLocations: classpath:/mapper/test2/*.xml # mybatis配置路徑 configLocation: # entity的包 typeAliasesPackage: com.zhangshuo/test2/entity # 全局配置 globalConfiguration: # id生成策略 0 自增 1 用戶輸入 idType: 0 # 靈據數類型 dbType: mysql # 字段是否爲下劃線格式 dbColumnUnderline: false
import com.alibaba.druid.pool.DruidDataSource; import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean; import com.zhangshuo.common.dataSource.DynamicDataSource; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.sql.DataSource; import java.util.Map; import java.sql.SQLException; import java.util.HashMap; /** * Created by Administrator on 2017/5/31 0031. */ @Configuration @MapperScan(value ={"com.zhangshuo.test1.mapper","com.zhangshuo.test2.mapper"}) publicclassDataSourceConfig{ @ConfigurationProperties(prefix ="datasource1") @Bean(name ="datasource1") // @Primary /** * 在方法上註解configurationProperties時,將會把屬性注入到返回結果的bean中 */ publicDruidDataSource dataSource1()throwsSQLException{ returnnewDruidDataSource(); } @ConfigurationProperties(prefix ="datasource2") @Bean(name ="datasource2") /** * 在方法上註解configurationProperties時,將會把屬性注入到返回結果的bean中 */ publicDruidDataSource dataSource2()throwsSQLException{ returnnewDruidDataSource(); } @Bean(name ="datasource") @Primary publicDynamicDataSource dynamicDataSource(@Qualifier(value ="datasource1")DataSource dataSource1,@Qualifier(value ="datasource2")DataSource dataSource2){ DynamicDataSource bean =newDynamicDataSource(); Map<Object,Object> targetDataSources =newHashMap<>(); targetDataSources.put("datasource1",dataSource1); targetDataSources.put("datasource2", dataSource2); bean.setTargetDataSources(targetDataSources); bean.setDefaultTargetDataSource(dataSource1); return bean; } @Bean(name ="sessionFactory1") @ConfigurationProperties(prefix ="mybatis-plus1") @ConfigurationPropertiesBinding() @Primary publicMybatisSqlSessionFactoryBean sqlSessionFactory1(@Qualifier(value ="datasource")DataSource dataSource){ MybatisSqlSessionFactoryBean bean =newMybatisSqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean; } @Bean(name ="sessionFactory2") @ConfigurationProperties(prefix ="mybatis-plus2") @ConfigurationPropertiesBinding() publicMybatisSqlSessionFactoryBean sqlSessionFactory2(@Qualifier(value ="datasource")DataSource dataSource){ MybatisSqlSessionFactoryBean bean =newMybatisSqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean; } }
在這裏說明下個人目錄結構:
com.zhangshuo.test1.controller/service/mapper
com.zhangshuo.test2.controller/service/mappersession
在dao層進行切換mybatis
import com.zhangshuo.common.dataSource.DBTypeEnum; import com.zhangshuo.common.dataSource.DbContextHolder; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * Created by Administrator on 2017/5/31 0031. * 以dao層進行切換 */ @Component @Aspect publicclassDataSourceInterceptor{ Logger logger =LoggerFactory.getLogger(DataSourceInterceptor.class); @Pointcut(value ="execution(public * com.zhangshuo.test1.mapper.**.*(..))") privatevoid datasource1ServicePointcut(){}; @Pointcut(value ="execution(public * com.zhangshuo.test2.mapper.**.*(..))") privatevoid datasource2ServicePointcut(){}; /** * 切換數據源1 */ @Before("datasource1ServicePointcut()") publicvoid dataSource1Interceptor(){ logger.debug("切換到數據源{}..............................","datasource1"); DbContextHolder.setDbType(DBTypeEnum.datasource1); } /** * 切換數據源2 */ @Before("datasource2ServicePointcut()") publicvoid dataSource2Interceptor(){ logger.debug("切換到數據源{}.......................","datasource2"); DbContextHolder.setDbType(DBTypeEnum.datasource2); } }
到這裏就能夠進行測試了;
順帶貼下mybatis-plus的分頁插件,我是定義到了mybatis-config.xml中,也能夠手動在sqlSessionfacotry中的setPlugins中()定義;app
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-config.dtd"> <configuration> <settings> <setting name="cacheEnabled" value="false"/> <setting name="lazyLoadingEnabled" value="false"/> <setting name="aggressiveLazyLoading" value="true"/> <setting name="logImpl" value="slf4j"/> </settings> <plugins> <plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"> <property name="dialectType" value="mysql" /> <property name="optimizeType" value="aliDruid" /> </plugin> </plugins> </configuration>