spring boot集成mybatisplus动态数据源切换

项目里面用到了数据源切换记录一下 ,防止以后忘了

需要以下几个类

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做动态数据库切换
在这里插入图片描述

在这里插入图片描述
以下是demo源码
https://pan.baidu.com/s/1hu3hXEnQLLCnuhr6Mnii8A

猜你喜欢

转载自blog.csdn.net/qq_39658059/article/details/85772340