MySql之SpringBoot集成动态数据源

导读:本篇文章讲解 MySql之SpringBoot集成动态数据源,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

概述

某些场景下,业务需要使用到多个数据库,这种场景下需要使用动态数据源的方式来执行相关sql。

多数据属性配置

#tomcat port
server.port=8080

# 主数据源配置
master.datasource.driver-class-name=com.mysql.jdbc.Driver
master.datasource.url=jdbc:mysql://192.168.195.129:3306/practice?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true
master.datasource.username=root
master.datasource.password=123456
# 从数据源配置
slave.datasource.driver-class-name=com.mysql.jdbc.Driver
slave.datasource.url=jdbc:mysql://192.168.195.129:3307/practice?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true
slave.datasource.username=root
slave.datasource.password=123456

#datasource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.195.129:3306/practice?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456

线程设置使用哪个数据库

public class MyThreadLocal {
    public static final ThreadLocal<String> local = new ThreadLocal<>();

    public static String getDataSource() {
        return local.get();
    }

    public static void setDataSource(String dataSource) {
        local.set(dataSource);
    }
}

自定义动态数据源类

package com.practice.tkmybatis.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 自定义动态数据源类用于在程序运行中切换数据源,并集成动态数据源的抽象父类
 */
public class MyDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return MyThreadLocal.getDataSource();
    }
}

动态数据源配置

package com.practice.tkmybatis.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
* 动态多数据源,这种方案我们需要自定义一个动态数据源的类,可以在程序运行过程中动态切换数据源。
* 缺点:
*   1、有很多的重复代码,例如springBoot中配置多个数据源的配置Bean;
*   2、切换主从进行读写操作时需要程序任务手动设置ThreadLocal中数据,这样就可能向从数据库中写数据;
*   3、如果有很多个从节点,那么我们没有办法进行负载均衡;
*   4、如果某个节点崩溃我们不能切换到另外一台节点中,不能故障转移;
* 注意:
*    如果需要解决上面的问题,我们需要自己写一套管理代码来动态的切换数据源进行读写分离,故障转移等。
**/
@Configuration
@MapperScan(basePackages = {"com.practice.tkmybatis.mapper"}, sqlSessionFactoryRef = "sqlSessionFactoryBean")
public class DataSourceConfig {

    /**
     * 主库属性
     */
    @Value("${master.datasource.driver-class-name}")
    private String masterDriverClassName;

    @Value("${master.datasource.url}")
    private String masterUrl;

    @Value("${master.datasource.username}")
    private String masterUserName;

    @Value("${master.datasource.password}")
    private String masterPassword;

    /**
     * 从库属性
     */
    @Value("${slave.datasource.driver-class-name}")
    private String slaveDriverClassName;

    @Value("${slave.datasource.url}")
    private String slaveUrl;

    @Value("${slave.datasource.username}")
    private String slaveUserName;

    @Value("${slave.datasource.password}")
    private String slavePassword;

    /**
     * 主库配置
     *
     * @return
     */
    @Bean
    public DruidDataSource masterDruidDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(masterDriverClassName);
        druidDataSource.setUrl(masterUrl);
        druidDataSource.setUsername(masterUserName);
        druidDataSource.setPassword(masterPassword);
        return druidDataSource;
    }

    /**
     * 从库配置
     *
     * @return
     */
    @Bean
    public DruidDataSource slaveDruidDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(slaveDriverClassName);
        druidDataSource.setUrl(slaveUrl);
        druidDataSource.setUsername(slaveUserName);
        druidDataSource.setPassword(slavePassword);
        return druidDataSource;
    }

    /**
     * 配置动态数据类
     *
     * @param masterDruidDataSource 主数据源
     * @param slaveDruidDataSource  从数据源
     * @return 动态数据源
     */
    public MyDataSource myDataSource(DruidDataSource masterDruidDataSource, DruidDataSource slaveDruidDataSource) {
        MyDataSource myDataSource = new MyDataSource();
        myDataSource.setDefaultTargetDataSource(masterDruidDataSource);
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("master", masterDruidDataSource);
        dataSourceMap.put("slave", slaveDruidDataSource);
        myDataSource.setTargetDataSources(dataSourceMap);
        return myDataSource;
    }

    public SqlSessionFactoryBean sqlSessionFactoryBean(MyDataSource myDataSource) {
        final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(myDataSource);
        return sqlSessionFactoryBean;
    }

    // 测试方法
    public static void main(String[] args) {
        MyThreadLocal.setDataSource("master");
        // 执行master库的逻辑
        MyThreadLocal.setDataSource("slave");
        // 执行slave库的逻辑
    }
}

参考

MySQL集群-SpringBoot集成多数据源
SpringBoot集成AbstractRoutingDataSource实现动态切换多数据源

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100043.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!