1. 程式人生 > >spring boot整合mybatisplus動態資料來源切換

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