1. 程式人生 > >springBoot 動態資料來源以及Mybatis多資料來源

springBoot 動態資料來源以及Mybatis多資料來源

原文地址:https://blog.csdn.net/tengxing007/article/details/78424645

前言

在開發過程中可能需要用到多個數據源,比如一個專案(MySQL)就是和(SQL Server)混合使用,就需要使用多資料來源;如果業務場景比較復炸,可以使用動態資料來源,靈活切換,典型的應用就是讀寫分離。下面分兩個模組來配置資料來源,大家可以根據自己實際情況配置。

多資料來源

禁用DataSourceAutoConfiguration

如果DataSourceAutoConfiguration不禁用的話,就會報錯,多個數據源,無法裝配哪一個。在springBoot的主程式入口的註解

@SpringBootApplication
(exclude = { DataSourceAutoConfiguration.class })
  • 配置application.properties
#datasource 這是自動裝配的預設配置禁止,這裡不能使用
#spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/api_resources?#autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
#spring.datasource.username=api #spring.datasource.password=api #db1 spring.datasource.db1.url=jdbc:mysql://127.0.0.1:3306/api_resources?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true spring.datasource.db1.username=api spring.datasource.db1.password=api spring.datasource
.db1.driver-class-name=com.mysql.jdbc.Driver #db2 spring.datasource.db2.url=jdbc:mysql://127.0.0.1:3306/ssm?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true spring.datasource.db2.username=api spring.datasource.db2.password=api spring.datasource.db2.driver-class-name=com.mysql.jdbc.Driver

配置dataSource

配置兩個資料來源,分別為db1,和db2

/**
 * Author: Starry.Teng
 * Email: [email protected]
 * Date: 17-11-1
 * Time: 下午9:14
 * Describe: DataSource Config
 */
@Configuration
public class DataSourceConfig {
    @Autowired
    Environment env;

    @Bean(name = "ds1")
    public DataSource dataSource1() {
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setUrl(env.getProperty("spring.datasource.db1.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.db1.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.db1.password"));
        dataSource.setDriverClassName(env.getProperty("spring.datasource.db1.driver-class-name"));
        return dataSource;
    }

    @Bean(name = "ds2")
    public DataSource dataSource2() {
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setUrl(env.getProperty("spring.datasource.db2.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.db2.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.db2.password"));
        dataSource.setDriverClassName(env.getProperty("spring.datasource.db2.driver-class-name"));
        return dataSource;
    }

}

Mybatis配置

為兩個資料來源分貝配置一個MybatisDb1Config類和MybatisDb2Config類,對資料來源進行管理,注意他們所管理的包是不同的。

/**
 * Author: Starry.Teng
 * Email: [email protected]
 * Date: 17-11-1
 * Time: 下午9:15
 * Describe: MybatisDb1 Config
 */
@Configuration
@MapperScan(basePackages = {"cn.yjxxclub.demo.datasource.dao.db1"}, sqlSessionFactoryRef = "sqlSessionFactory1")
public class MybatisDb1Config {

    @Qualifier("ds1")
    @Autowired
    DataSource dataSource;

    @Bean(name = "sqlSessionFactory1")
    public SqlSessionFactory sqlSessionFactory1() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factoryBean.setMapperLocations(resolver.getResources("classpath:mappers/db1/*.xml"));
        factoryBean.setTypeAliasesPackage("cn.yjxxclub.demo.datasource.model");
        return factoryBean.getObject();

    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate1() throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory1()); // 使用上面配置的Factory
        return template;
    }
}
/**
 * Author: Starry.Teng
 * Email: [email protected]
 * Date: 17-11-1
 * Time: 下午9:26
 * Describe: MybatisDb2 Config
 */
@Configuration
@MapperScan(basePackages = {"cn.yjxxclub.demo.datasource.dao.db2"}, sqlSessionFactoryRef = "sqlSessionFactory2")
public class MybatisDb2Config {

    @Qualifier("ds2")
    @Autowired
    DataSource dataSource;

    @Bean(name = "sqlSessionFactory2")
    public SqlSessionFactory sqlSessionFactory2() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factoryBean.setMapperLocations(resolver.getResources("classpath:mappers/db2/*.xml"));
        factoryBean.setTypeAliasesPackage("cn.yjxxclub.demo.datasource.model");
        return factoryBean.getObject();

    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate2() throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory2());
        return template;
    }
}

編寫Dao和Mapper

Mapper.java和mapper.xml在basePackages和classpath對應放置即可,和springboot整合Mybtis一樣,這裡就不說了,然後正常啟動即可。程式碼在此:https://github.com/tengxing/Multiple-dataSources

資料來源動態切換

資料來源註冊

/**
 * Author: Starry.Teng
 * Email: [email protected]
 * Date: 17-11-1
 * Time: 下午9:14
 * Describe: DataSource Config
 */
@Configuration
public class DataSourceConfig {
    @Autowired
    Environment env;

    @Bean(name = "ds1")
    public DataSource dataSource1() {
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setUrl(env.getProperty("spring.datasource.db1.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.db1.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.db1.password"));
        dataSource.setDriverClassName(env.getProperty("spring.datasource.db1.driver-class-name"));
        return dataSource;
    }

    @Bean(name = "ds2")
    public DataSource dataSource2() {
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setUrl(env.getProperty("spring.datasource.db2.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.db2.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.db2.password"));
        dataSource.setDriverClassName(env.getProperty("spring.datasource.db2.driver-class-name"));
        return dataSource;
    }

    @Bean(name = "dynamicDS1")//注意這個bean是mybatis的sqlSessionFacatory所管理的dataSource
    public DataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 預設資料來源
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());

        // 配置多資料來源
        Map<Object, Object> dsMap = new HashMap(5);
        dsMap.put("ds1", dataSource1());
        dsMap.put("ds2", dataSource2());

        dynamicDataSource.setTargetDataSources(dsMap);

        return dynamicDataSource;
    }

}

動態資料來源編寫

需要繼承AbstractRoutingDataSource類

/**
 * Author: http://blog.csdn.net/neosmith/article/details/61202084
 * Date: 17-11-2
 * Time: 下午2:56
 * Describe: 動態資料來源
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final Logger log = LoggerFactory.getLogger(DynamicDataSource.class);

    @Override
    protected Object determineCurrentLookupKey() {
        log.debug("資料來源為{}", DataSourceContextHolder.getDB());

        return DataSourceContextHolder.getDB();
    }
}

編寫DataSourceContextHolder

/**
 * Author: http://blog.csdn.net/neosmith/article/details/61202084
 * Date: 17-11-2
 * Time: 下午2:56
 * Describe: DataSource ContextHolder
 */
public class DataSourceContextHolder {
    public static final Logger log = LoggerFactory.getLogger(DataSourceContextHolder.class);

    /**
     * 預設資料來源
     */
    public static final String DEFAULT_DS = "ds1";

    /**
     * 獲取當前執行緒
     */
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    // 設定資料來源名
    public static void setDB(String dbType) {
        log.debug("切換到{}資料來源", dbType);
        contextHolder.set(dbType);
    }

    // 獲取資料來源名
    public static String getDB() {
        return (contextHolder.get());
    }

    // 清除資料來源名
    public static void clearDB() {
        contextHolder.remove();
    }
}

咋們到時候只要呼叫setDB()方法即可實現資料來源的切換,下面使用Aop的方式進行動態切換。

編寫代理類

/**
 * Author: http://blog.csdn.net/neosmith/article/details/61202084
 * Date: 17-11-2
 * Time: 下午3:01
 * Describe: 動態資料來源代理類
 * 邏輯:對方法@DB註解的方法進行切面換資料來源操作
 */
@Aspect
@Component
@Order(value=-1) //保證該AOP在@Transactional之前執行
public class DynamicDataSourceAspect {

    @Before("@annotation(DB)")
    public void beforeSwitchDS(JoinPoint point){

        //獲得當前訪問的class
        Class<?> className = point.getTarget().getClass();

        //獲得訪問的方法名
        String methodName = point.getSignature().getName();
        //得到方法的引數的型別
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
        String dataSource = DataSourceContextHolder.DEFAULT_DS;
        try {
            // 得到訪問的方法物件
            Method method = className.getMethod(methodName, argClass);

            // 判斷是否存在@DS註解
            if (method.isAnnotationPresent(DB.class)) {
                DB annotation = method.getAnnotation(DB.class);
                // 取出註解中的資料來源名
                dataSource = annotation.value();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 切換資料來源
        DataSourceContextHolder.setDB(dataSource);

    }
    @After("@annotation(DB)")
    public void afterSwitchDS(JoinPoint point){

        DataSourceContextHolder.clearDB();

    }
}

自定義註解

/**
 * Author: Starry.Teng
 * Email: [email protected]
 * Date: 17-11-2
 * Time: 下午3:00
 * Describe:
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({
        ElementType.METHOD
})
public @interface DB {
    String value() default "ds1";
}

serviceImpl

    @DB("ds1")
    public Object getDs1(){

        Singer singer = singerMapper.findByName("陳奕迅");
        logger.info("/n"+singer);
        return null;
    }

    @DB("ds2")
    public Object getDs2(){
        Book book = bookMapper.findById(bookMapper.list().get(0).getId());
        logger.info(book+"/n");
        return null;
    }

兩者比較

類別多資料來源動態資料來源
作用配置多個數據源,分模組開發通過靈活的手段對資料庫進行靈活切庫
原理例項化多個SsqlSessionFactorySpring+AOP
作用框架MybatisSpring
應用場景解耦比較大的專案,模組化開發主從分佈,讀寫分離

知識點

上面的兩種方式都達到了”換資料來源”目的,只是實現的原理和方式不一樣而已,都是優虐,還是那句話,沒有最好的方法,只有在特定的環境下最適合的解決方案。

相關推薦

springBoot 動態資料來源以及Mybatis資料來源

原文地址:https://blog.csdn.net/tengxing007/article/details/78424645前言在開發過程中可能需要用到多個數據源,比如一個專案(MySQL)就是和(SQL Server)混合使用,就需要使用多資料來源;如果業務場景比較復炸,

springboot 整合 pagehelper + tk-mybatis 資料來源問題

             閒暇之餘,寫點最近的收穫,寫一點心得,便於以後參考方便,另外可以幫助有這樣需求的人少走彎路。          整合多個數據源,很多部落格會提到springboot整合jdbcTemplete為例子,網上有很多,今天主要推薦的是整合 pagehelp

springboot+mybatis資料來源配置,AOP註解動態切換資料來源

轉載至:https://blog.csdn.net/xiaosheng_papa/article/details/80218006 親測有效。 注:有些系統中已經配置了單資料來源,現在要轉成多資料來源,可能需要額外的配置。拿我自己當前專案來說: 專案在啟動類中配置了單資料來源:

基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 資料來源配置

Github 地址:github.com/Snailclimb/…(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 SpringBoot2.0+,是你學習SpringBoot 的最佳指南。) ,歡迎各位 Star。

新手也能看懂,基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 資料來源配置

Github 地址:https://github.com/Snailclimb/springboot-integration-examples(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 S

Mybatis(攔截器實現)通用mapper及全ORM實現(五)-- springboot+mybatis資料來源設定

本篇實際上和mybatisext專案並沒有太大關係了,但在實際專案中脫離不開多個數據源,尤其是主從分離,同樣網上一些資料大同小異而且大部分並不能真正解決問題,所以單獨提出來說一下 假設我們就是要解決一個主從分離,資料來源定義在了application.properties中

springboot+mybatis資料來源配置實現

簡單實現了根據註解動態切換資料來源,支援同一個資料庫的宣告式事務,但不支援JTA事務。處理流程: 根據配置的資料來源資訊,建立動態資料來源bean 利用DataSourceAspect處理@DataSource註解,設定當前要使用的具體資料來源 pom.xm

SpringBoot整合Mybatis資料來源(Atomikos)

一、 Spring介紹 1.1、SpringBoot簡介 在您第1次接觸和學習Spring框架的時候,是否因為其繁雜的配置而退卻了?在你第n次使用Spring框架的時候,是否覺得一堆反覆黏貼的配置有一些厭煩?那麼您就不妨來試試使用Spring Boot來讓你更易上手,更簡

SpringBoot入門之基於Druid配置Mybatis資料來源

上一篇瞭解了Druid進行配置連線池的監控和慢sql處理,這篇瞭解下使用基於基於Druid配置Mybatis多資料來源。SpringBoot預設配置資料庫連線資訊時只需設定url等屬性資訊就可以了,SpringBoot就會基於約定根據配置資訊例項化物件,但是一般大型的專案都是

springboot + mybatis 資料來源

1:首先在springboot的 main啟動類上加 // boot自帶的DataSourceAutoConfiguration禁掉,因為它會讀取application.properties檔案的spring.datasource.*屬性並自動配置單資料來源。在@Sprin

eclipse 使用maven 搭建 springboot+mybatis + 資料來源

DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(19) NOT NULL auto_increment, `loginname` varchar(64) default NULL, `name` varchar(64)

spring-boot (四) springboot+mybatis資料來源最簡解決方案

配置檔案 pom包就不貼了比較簡單該依賴的就依賴,主要是資料庫這邊的配置: mybatis.config-locations=classpath:mybatis/mybatis-config.xml spring.datasource.test1.driverClassName = com.

springboot(七):springboot+mybatis資料來源最簡解決方案

說起多資料來源,一般都來解決那些問題呢,主從模式或者業務比較複雜需要連線不同的分庫來支援業務。我們專案是後者的模式,網上找了很多,大都是根據jpa來做多資料來源解決方案,要不就是老的spring多資料來源解決方案,還有的是利用aop動態切換,感覺有點小複雜,其實

springboot+jpa+mybatis 資料來源支援

package com.ehaoyao.paycenter.job.common.config;/** * ERP資料來源配置類 * * @author PF * Created by dell on 2018-05-04. */ import org.springframework.beans.

springboot整合mybatis資料來源

application.properties #mysql [email protected]@ spring.datasource.primary.username= @[email protected] spring.datasource.prim

springboot+mybatis資料來源配置方法及遇到的問題

這裡做的測試,兩個資料庫內表都一樣 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"

SpringBoot下配置Mybatis資料來源

package com.ai.demos.manager; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactor

Spring Boot MyBatis 動態資料來源切換、資料來源,讀寫分離

轉載自:https://blog.csdn.net/u013360850/article/details/78861442本專案使用 Spring Boot 和 MyBatis 實現多資料來源,動態資料來源的切換;有多種不同的實現方式,在學習的過程中發現沒有文章將這些方式和常

Spring+Mybatis資料來源配置(四)——AbstractRoutingDataSource實現資料來源動態切換

有時候需要在程式中動態切換資料來源,那麼這個系列的之前的博文所闡述的方法就不再使用了,總不能通過程式更改config.properties檔案的dataSource的值,然後再重啟web伺服器以便載入applicationContext.xml檔案。這裡講訴的是如何利用Ab

mybatis 資料來源動態切換

>筆者主要從事c#開發,近期因為專案需要,搭建了一套spring-cloud微服務框架,集成了eureka服務註冊中心、 gateway閘道器過濾、admin服務監控、auth授權體系驗證,集成了redis、swagger、jwt、mybatis多資料來源等各項功能。 具體搭建過程後續另寫播客介紹。具體結構如