spring boot整合mybatisplus動態資料來源切換
阿新 • • 發佈:2019-01-10
專案裡面用到了資料來源切換記錄一下 ,防止以後忘了
需要以下幾個類
DatabaseConfiguration.java
DataSourceSwitch.java
DataSourceSwitchAspect.java
DbContextHolder.java
DBTypeEnum.java
DynamicDataSource.java
MybatisPlusConfig.java
DataSourceSwitchAspect aop類 切換到指定的資料來源
/**
*@Project: demo
*@Author: chenlijun
*@Date: 2019年1月9日
*@Copyright: ©2016-2022 http://www.zhtkj.com Inc. All rights reserved.
*/
package com.example.demo.config;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* ClassName: DataSourceSwitchAspect
* @Description: TODO
* @author chenlijun
* @date 2019年1月9日
*/
@Component
@Aspect
@Order(-100)
public class DataSourceSwitchAspect {
@Before("@annotation(com.example.demo.config.DataSourceSwitch)")
public void xdkj (JoinPoint joinPoint) {
System.out. println("切換到dept資料來源");
//setDataSource(joinPoint, DBTypeEnum.dept);
DbContextHolder.setDbType(DBTypeEnum.dept);
}
@After("@annotation(com.example.demo.config.DataSourceSwitch)")
public void gateway2 (JoinPoint joinPoint) {
System.out.println("切換到user資料來源");
//setDataSource(joinPoint, DBTypeEnum.user);
DbContextHolder.setDbType(DBTypeEnum.user);
}
}
DbContextHolder 類
/**
*@Project: demo
*@Author: chenlijun
*@Date: 2019年1月9日
*@Copyright: ©2016-2022 http://www.zhtkj.com Inc. All rights reserved.
*/
package com.example.demo.config;
/**
* ClassName: DbContextHolder
* @Description: TODO
* @author chenlijun
* @date 2019年1月9日
*/
public class DbContextHolder {
//get()方法是用來獲取ThreadLocal在當前執行緒中儲存的變數副本,set()用來設定當前執行緒中變數的副本,remove()用來移除當前執行緒中變數的副本
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 設定資料來源
* @param dbTypeEnum
*/
public static void setDbType(DBTypeEnum dbTypeEnum) {
contextHolder.set(dbTypeEnum.getValue());
}
/**
* 取得當前資料來源
* @return
*/
public static String getDbType() {
return (String) contextHolder.get();
}
/**
* 清除上下文資料
*/
public static void clearDbType() {
contextHolder.remove();
}
}
DBTypeEnum 列舉類 可以指定多個數據庫
/**
*@Project: demo
*@Author: chenlijun
*@Date: 2019年1月9日
*@Copyright: ©2016-2022 http://www.zhtkj.com Inc. All rights reserved.
*/
package com.example.demo.config;
/**
* ClassName: DBTypeEnum
* @Description: TODO
* @author chenlijun
* @date 2019年1月9日
*/
public enum DBTypeEnum {
user("user"),dept("dept");
private String value;
DBTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
DynamicDataSource
/**
*@Project: demo
*@Author: chenlijun
*@Date: 2019年1月9日
*
*/
package com.example.demo.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* ClassName: DynamicDataSource
* @Description: TODO
* @author chenlijun
* @date 2019年1月9日
*/
public class DynamicDataSource extends AbstractRoutingDataSource{
/**
* 取得當前使用哪個資料來源
* @return
*/
@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
MybatisPlusConfig 配置類
/**
*@Project: demo
*@Author: chenlijun
*@Date: 2019年1月9日
*@Copyright: ©2016-2022 http://www.zhtkj.com Inc. All rights reserved.
*/
package com.example.demo.config;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
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 org.springframework.transaction.annotation.EnableTransactionManagement;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
/**
* ClassName: MybatisPlusConfig
* @Description: TODO
* @author chenlijun
* @date 2019年1月9日
*/
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages="com.example.demo.**.mapper")
public class MybatisPlusConfig {
/* 效能分析攔截器(外掛),用於輸出每條 SQL 語句及其執行時間
@Bean
public PerformanceInterceptor performanceInterceptor () {
return new PerformanceInterceptor();
}
分頁外掛
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//paginationInterceptor.setLocalPage(true);// 開啟 PageHelper 的支援
return paginationInterceptor;
}
*/
@Bean(name = "user")
@ConfigurationProperties(prefix = "spring.datasource.user" )
public DataSource user () {
System.out.println("spring.datasource.user");
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "dept")
@ConfigurationProperties(prefix = "spring.datasource.dept" )
public DataSource dept () {
return DruidDataSourceBuilder.create().build();
}
/**
* 動態資料來源配置
* @return
*/
@Bean
@Primary
public DataSource multipleDataSource (@Qualifier("user") DataSource user,
@Qualifier("dept") DataSource dept) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map< Object, Object > targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.user.getValue(), user );
targetDataSources.put(DBTypeEnum.dept.getValue(), dept);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(user);
return dynamicDataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(multipleDataSource(user(),dept()));//設定資料來源
sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/com/example/**/**/mapping/*.xml"));
//設定mybatisplus引數
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
sqlSessionFactory.setConfiguration(configuration);
/*設定買mybatisplus 的外掛支援
sqlSessionFactory.setPlugins(new Interceptor[]{
paginationInterceptor(),
performanceInterceptor()
});*/
return sqlSessionFactory.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory); // 使用上面配置的Factory
return template;
}
}
DataSourceSwitch 類
自定義註解,在方法上加@ DataSourceSwitch 就可以切換資料庫了
package com.example.demo.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataSourceSwitch {
DBTypeEnum value() default DBTypeEnum.user;
}
寫好配置好後,寫一個簡單的查詢。在資料庫新建user和dept資料庫。 查詢做動態切換
在service層方法上加上@DataSourceSwitch做動態資料庫切換