项目里面用到了数据源切换记录一下 ,防止以后忘了
需要以下几个类
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做动态数据库切换