springboot+mybatis+druid配置動態(tài)數(shù)據(jù)源

一雕拼、建數(shù)據(jù)庫和表

1.數(shù)據(jù)庫demo1放一張user表
SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'aa');
INSERT INTO `user` VALUES ('2', 'bb');
2.數(shù)據(jù)庫demo2放一張role表
SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'CC');
INSERT INTO `role` VALUES ('2', 'DD');

二恋腕、pom.xml引入包

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>

        <!-- aop -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <!-- alibaba druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- dynamic-->
        <dependency>
            <groupId>com.typesafe.dynamicdatasource</groupId>
            <artifactId>dynamic-data-source_2.11</artifactId>
        </dependency>

三唧领、用generator插件生成user、role兩張表的實體類孽拷、mapper.java吨掌、mapper.xml

User.java
Role.java
UserMapper.java
RoleMapper.java
UserMapper.xml
RoleMapper.xml

四、配置application.yml

server:
  port: 8088

mybatis:
  mapper-locations: classpath:mapper/*.xml

spring:
  datasource:
      db1:
        url: jdbc:mysql://localhost:3306/demo1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        #驅(qū)動包
        driver-class-name: com.mysql.cj.jdbc.Driver
        #初始連接數(shù)
        initial-size: 5
        #最小空閑數(shù)
        min-idle: 5
        #最大活動數(shù)
        max-active: 20
        #等待超時時間
        max-wait: 60000
        #配置間隔多久才進行一次檢測脓恕,檢測需要關(guān)閉的空閑連接膜宋,單位是毫秒
        time-between-eviction-runs-millis: 60000
        # 配置一個連接在池中最小生存的時間,單位是毫秒
        min-evictable-idle-time-millis: 300000
        #驗證數(shù)據(jù)庫連接的查詢語句,MYSQL是select 1
        validation-query: SELECT 1 FROM DUAL
        #空閑時測試炼幔,testOnBorrow和testOnReturn在生產(chǎn)環(huán)境一般是不開啟的秋茫,主要是性能考慮。失效連接主要通過testWhileIdle保證
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        #打開PSCache乃秀,并指定每個鏈接上的PSCache大小
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        #配置監(jiān)控統(tǒng)計攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計肛著,‘wall’用于防火墻,此處是filter修改的地方
        filters: stat,wall
        #通過connectproperties屬性來打開mergesql功能:慢sql記錄
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
        #合并多個DruidDataSource
        useGlobalDataSourceStat: true
      db2:
        url: jdbc:mysql://localhost:3306/demo2?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        #驅(qū)動包
        driver-class-name: com.mysql.cj.jdbc.Driver
        #初始連接數(shù)
        initial-size: 5
        #最小空閑數(shù)
        min-idle: 5
        #最大活動數(shù)
        max-active: 20
        #等待超時時間
        max-wait: 60000
        #配置間隔多久才進行一次檢測跺讯,檢測需要關(guān)閉的空閑連接枢贿,單位是毫秒
        time-between-eviction-runs-millis: 60000
        # 配置一個連接在池中最小生存的時間,單位是毫秒
        min-evictable-idle-time-millis: 300000
        #驗證數(shù)據(jù)庫連接的查詢語句,MYSQL是select 1
        validation-query: SELECT 1 FROM DUAL
        #空閑時測試刀脏,testOnBorrow和testOnReturn在生產(chǎn)環(huán)境一般是不開啟的局荚,主要是性能考慮。失效連接主要通過testWhileIdle保證
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        #打開PSCache愈污,并指定每個鏈接上的PSCache大小
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        #配置監(jiān)控統(tǒng)計攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計危队,‘wall’用于防火墻,此處是filter修改的地方
        filters: stat,wall
        #通過connectproperties屬性來打開mergesql功能:慢sql記錄
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
        #合并多個DruidDataSource
        useGlobalDataSourceStat: true

五钙畔、啟動類掃描mapper.java文件

@SpringBootApplication
@MapperScan("com.example.demo.dao")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

六、定義DataSourceConfig金麸, 將application.yml中的配置導(dǎo)入DataSource中擎析,并注入到bean

@Configuration
public class DataSourceConfig {
    //從配置文件配置數(shù)據(jù)源
    @Primary
    @Bean(name="datasource1")
    @ConfigurationProperties("spring.datasource.db1")
    public DataSource dataSource1(){
        return new DruidDataSource();
    }

    //從配置文件配置數(shù)據(jù)源
    @Bean(name="datasource2")
    @ConfigurationProperties("spring.datasource.db2")
    public DataSource dataSource2(){
        return new DruidDataSource();
    }

    //動態(tài)數(shù)據(jù)源 進行數(shù)據(jù)源切換
    @Bean(name="dynamicDataSource")
    public DataSource dynamicDataSource(){
        DynamicDataSource dynamicDatasource=new DynamicDataSource();
        //設(shè)置默認(rèn)數(shù)據(jù)源
        dynamicDatasource.setDefaultTargetDataSource(dataSource1());
        //配置多數(shù)據(jù)源
        Map<Object,Object> dsMap=new HashMap<>();
        dsMap.put("datasource1",dataSource1());
        dsMap.put("datasource2",dataSource2());
        //將多數(shù)據(jù)源放到數(shù)據(jù)源池中
        dynamicDatasource.setTargetDataSources(dsMap);
        return dynamicDatasource;
    }
}

七、定義動態(tài)數(shù)據(jù)源切換類DynamicDataSourceContextHolder

public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder=new ThreadLocal<>();

    //設(shè)置數(shù)據(jù)源名稱
    public static void setDB(String dbType){
        contextHolder.set(dbType);
    }

    //獲取數(shù)據(jù)源名稱
    public static String getDB(){
        return contextHolder.get();
    }

    //清除數(shù)據(jù)源名
    public static void clearDB(){
        contextHolder.remove();
    }
}

八、定義獲取動態(tài)數(shù)據(jù)源類DynamicDataSource

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDB();
    }
}

九揍魂、定義mybatis配置類桨醋,將DynamicDataSource放入SqlSessionFactoryBean中

@EnableTransactionManagement
@Configuration
public class MyBatisConfig {
    @Resource(name = "dynamicDataSource")
    private DataSource dynamicDataSource;

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);//將動態(tài)數(shù)據(jù)源bean配置到sqlsessionfactory
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource);
    }
}

十、定義用于切換數(shù)據(jù)源的注解TargetDataSource

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    String value() default "datasource1";
}

十一现斋、定義切面DynamicDataSourceAspect喜最,用于攔截注解,并執(zhí)行數(shù)據(jù)源切換功能

@Aspect
@Component
public class DynamicDataSourceAspect {
    @Before("@annotation(targetDataSource)")
    public void beforeSwitchDS(JoinPoint point,TargetDataSource targetDataSource){
        DynamicDataSourceContextHolder.setDB(targetDataSource.value());
    }

    @After("@annotation(targetDataSource)")
    public void afterSwitchDS(JoinPoint point,TargetDataSource targetDataSource){
        DynamicDataSourceContextHolder.clearDB();
    }
}

十二庄蹋、測試類Test

@RestController
public class Test {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserMapper userMapper;

    //未使用TargetDataSource注解瞬内,則使用默認(rèn)數(shù)據(jù)源,即datasource1
    @RequestMapping("/ds1")
    public String selectDataSource1(){
        return userMapper.selectByPrimaryKey(1).toString();
    }

    //使用了注解限书,則數(shù)據(jù)源為注解中指定的datasource2
    @RequestMapping("/ds2")
    @TargetDataSource("datasource2")
    public String selectDataSource2(){
        return roleMapper.selectByPrimaryKey(1).toString();
    }
}

測試

1.輸入

http://localhost:8088/ds1

返回


DynamicDataSourceRegister_百度搜索.png

2.輸入

http://localhost:8088/ds2

返回


123545646.png
結(jié)論:兩次請求分別從不同的數(shù)據(jù)庫獲取到了數(shù)據(jù)虫蝶,多數(shù)據(jù)源配置成功!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末倦西,一起剝皮案震驚了整個濱河市能真,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扰柠,老刑警劉巖粉铐,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卤档,居然都是意外死亡蝙泼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門裆装,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踱承,“玉大人,你說我怎么就攤上這事哨免【セ睿” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵琢唾,是天一觀的道長载荔。 經(jīng)常有香客問我,道長采桃,這世上最難降的妖魔是什么懒熙? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮普办,結(jié)果婚禮上工扎,老公的妹妹穿的比我還像新娘。我一直安慰自己衔蹲,他們只是感情好肢娘,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般橱健。 火紅的嫁衣襯著肌膚如雪而钞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天拘荡,我揣著相機與錄音臼节,去河邊找鬼。 笑死珊皿,一個胖子當(dāng)著我的面吹牛网缝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亮隙,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼途凫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溢吻?” 一聲冷哼從身側(cè)響起维费,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎促王,沒想到半個月后犀盟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蝇狼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年阅畴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迅耘。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡贱枣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颤专,到底是詐尸還是另有隱情纽哥,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布栖秕,位于F島的核電站春塌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏簇捍。R本人自食惡果不足惜只壳,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暑塑。 院中可真熱鬧吼句,春花似錦、人聲如沸事格。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至尔艇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間么鹤,已是汗流浹背终娃。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒸甜,地道東北人棠耕。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像柠新,于是被迫代替她去往敵國和親窍荧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 關(guān)注數(shù)據(jù)蛙已經(jīng)大半年時間,進群也已經(jīng)大半年,現(xiàn)在處于脫產(chǎn)狀態(tài). 年初的時候有購買了一本 <MySQL必知必會> ,...
    AlexWhite閱讀 347評論 0 2
  • MySql提供了EXPLAIN語法用來進行查詢分析恨憎,在SQL語句前加一個"EXPLAIN"即可蕊退。比如我們要分析如下...
    hexm01閱讀 361評論 0 1
  • 1.$是拼接,#是占位憔恳,都可以達(dá)到數(shù)據(jù)綁定效果 2.如果數(shù)據(jù)庫多條數(shù)據(jù)符合條件瓤荔,那么 User user = fi...
    皮卡潔閱讀 152評論 0 0
  • > 有沒有這樣一樣情況,把一個集群中的某個表導(dǎo)到另一個群集中钥组,或者h(yuǎn)base的表結(jié)構(gòu)發(fā)生了更改输硝,但是數(shù)據(jù)還要,比如...
    kikiki5閱讀 134評論 0 2
  • 高并發(fā)下的緩存風(fēng)險點和使用 緩存是為了提高應(yīng)用服務(wù)的響應(yīng)時間程梦。是一種空間換時間典型應(yīng)用点把。 1.一個緩存只干一件事。...
    幸福樂呵呵閱讀 549評論 0 0