当前位置: 代码网 > it编程>编程语言>Java > Springboot如何设置多数据源,随时切换

Springboot如何设置多数据源,随时切换

2024年05月15日 Java 我要评论
需求接到一个任务,把一个数据库里面的数据定时导入到另外的数据库中但是又不允许我们通过binlog+canal同步,所以考虑起一个微服务充当同步脚本的作用且配置多数据库,并且支持随时切换环境1、mysq

需求

接到一个任务,把一个数据库里面的数据定时导入到另外的数据库中

但是又不允许我们通过binlog+canal同步,所以考虑起一个微服务充当同步脚本的作用

且配置多数据库,并且支持随时切换

环境

  • 1、mysql多个库
  • 2、mysql+postgresql

思路

spring框架本身支持多数据源,我们查看他的定义

spring的多数据源支持—abstractroutingdatasource,abstractroutingdatasource定义了抽象的determinecurrentlookupkey方法,子类实现此方法,来确定要使用的数据源

看下下面它的源码:

public abstract class abstractroutingdatasource extends abstractdatasource implements initializingbean {
	 protected datasource determinetargetdatasource() {
		assert.notnull(this.resolveddatasources, "datasource router not initialized");
		object lookupkey = determinecurrentlookupkey();
		datasource datasource = this.resolveddatasources.get(lookupkey);
		if (datasource == null && (this.lenientfallback || lookupkey == null)) {
			datasource = this.resolveddefaultdatasource;
		}
		if (datasource == null) {
			throw new illegalstateexception("cannot determine target datasource for lookup key [" + lookupkey + "]");
		}
		return datasource;
	}

        // 确定当前要使用的数据源
        protected abstract object determinecurrentlookupkey();
}

所以我们只要写一个自定义类去继承上面这个abstractroutingdatasource类,并重写determinecurrentlookupkey 方法即可

操作

包如下:

一、多个库都是mysql类型

pom依赖

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
         xsi:schemalocation="http://maven.apache.org/pom/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0</modelversion>
    <parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>2.6.7</version>
        <relativepath/> <!-- lookup parent from repository -->
    </parent>
    <groupid>com.example</groupid>
    <artifactid>db-demo</artifactid>
    <version>0.0.1-snapshot</version>
    <name>db-demo</name>
    <description>demo project for spring boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</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.2.2</version>
        </dependency>

        <dependency>
            <groupid>mysql</groupid>
            <artifactid>mysql-connector-java</artifactid>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-test</artifactid>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupid>org.springframework.boot</groupid>
                <artifactid>spring-boot-maven-plugin</artifactid>
            </plugin>
        </plugins>
    </build>

</project>

1、配置文件application.yml

#端口
server.port: 7788
spring.application.name: bddemo

# mysql
spring.datasource:
  driver-class-name: com.mysql.cj.jdbc.driver
  #数据库1
  db1:
    jdbc-url: jdbc:mysql://127.0.0.1:3306/db1?servertimezone=gmt%2b8&useunicode=true&characterencoding=utf8&usessl=false
    username: root
    password: 123456
  #数据库2
  db2:
    jdbc-url: jdbc:mysql://127.0.0.1:3306/db2?servertimezone=gmt%2b8&useunicode=true&characterencoding=utf8&usessl=false
    username: root
    password: 123456

# mybatis
mybatis:
  mapper-locations: classpath:mapper/*mapper.xml
  type-aliases-package: ccom.example.demo.*.entity

2、配置类

1) datasourceconfig 数据库配置类:

import org.springframework.boot.context.properties.configurationproperties;
import org.springframework.boot.jdbc.datasourcebuilder;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.context.annotation.primary;
import org.springframework.jdbc.datasource.datasourcetransactionmanager;
import org.springframework.transaction.platformtransactionmanager;
import javax.sql.datasource;
import java.util.hashmap;
import java.util.map;
/**
* 数据库配置
* @date 2022/5/19
*/
@configuration
public class datasourceconfig {

    /**
     * 数据源1
     * spring.datasource.db1:application.properteis中对应属性的前缀
     * @return
     */
    @bean(name = "db1")
    @configurationproperties(prefix = "spring.datasource.db1")
    public datasource datasourceone() {
        return datasourcebuilder.create().build();
    }

    /**
     * 数据源2
     * spring.datasource.db2:application.properteis中对应属性的前缀
     * @return
     */
    @bean(name = "db2")
    @configurationproperties(prefix = "spring.datasource.db2")
    public datasource datasourcetwo() {
        return datasourcebuilder.create().build();
    }

    /**
     * 动态数据源: 通过aop在不同数据源之间动态切换
     * @return
     */
    @primary
    @bean(name = "dynamicdatasource")
    public datasource dynamicdatasource() {
        dynamicdatasource dynamicdatasource = new dynamicdatasource();
        // 默认数据源
        dynamicdatasource.setdefaulttargetdatasource(datasourceone());
        // 配置多数据源
        map<object, object> dsmap = new hashmap<>();
        dsmap.put("db1", datasourceone());
        dsmap.put("db2", datasourcetwo());

        dynamicdatasource.settargetdatasources(dsmap);
        return dynamicdatasource;
    }

    /**
     * 配置多数据源后ioc中存在多个数据源了,事务管理器需要重新配置,不然器不知道选择哪个数据源
     * 事务管理器此时管理的数据源将是动态数据源dynamicdatasource
     * 配置@transactional注解
     * @return
     */
    @bean
    public platformtransactionmanager transactionmanager() {
        return new datasourcetransactionmanager(dynamicdatasource());
    }
}

2) dynamicdatasource 动态数据源类:

import com.example.demo.utils.datasourceutil;
import org.springframework.jdbc.datasource.lookup.abstractroutingdatasource;
/**
 * 动态数据源类
 * @date 2022/2/11
 */
public class dynamicdatasource extends abstractroutingdatasource {
    @override
    protected object determinecurrentlookupkey() {
        return datasourceutil.getdb();
    }
}

3、切换工具类:datasourceutil

/**
* 数据源切换工具
 * @date 2022/5/19
*/
public class datasourceutil {
    /**
     * 默认数据源
     */
    public static final string default_ds = "db1";
    /**
    *  数据源属于一个公共的资源
    *  采用threadlocal可以保证在多线程情况下线程隔离
    */
    private static final threadlocal<string> contextholder = new threadlocal<>();

    /**
     * 设置数据源名
     * @param dbtype
     */
    public static void setdb(string dbtype) {
        contextholder.set(dbtype);
    }

    /**
     * 获取数据源名
     * @return
     */
    public static string getdb() {
        return (contextholder.get());
    }

    /**
     * 清除数据源名
     */
    public static void cleardb() {
        contextholder.remove();
    }
}

4、启动

(1)启动类中配置移除默认的数据库配置类

import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.boot.autoconfigure.jdbc.datasourceautoconfiguration;

//移除默认数据库配置类
@springbootapplication(exclude = {datasourceautoconfiguration.class})
public class dbdemoapplication {

    public static void main(string[] args) {
        springapplication.run(dbdemoapplication.class, args);
    }

}

(2)测试

结果

  • db1库

  • db2库

二、一个是mysql一个是postgresql

1、pom依赖新增

    <dependency>
        <groupid>org.postgresql</groupid>
        <artifactid>postgresql</artifactid>
        <scope>runtime</scope>
    </dependency>

2、配置文件application.yml

#端口
server.port: 7788
spring.application.name: bddemo

# mysql
spring.datasource:
  #数据库1
  db1:
    driver-class-name: com.mysql.cj.jdbc.driver
    jdbc-url: jdbc:mysql://127.0.0.1:3306/db1?servertimezone=gmt%2b8&useunicode=true&characterencoding=utf8&usessl=false
    username: root
    password: 123456
  #数据库2
  db2:
#    driver-class-name: com.mysql.cj.jdbc.driver
#    jdbc-url: jdbc:mysql://127.0.0.1:3306/db2?servertimezone=gmt%2b8&useunicode=true&characterencoding=utf8&usessl=false
#    username: root
#    password: 123456
    driver-class-name: org.postgresql.driver
    jdbc-url: jdbc:postgresql://127.0.0.1:5432/test?servertimezone=gmt%2b8&useunicode=true&characterencoding=utf8&usessl=false
    username: postgres
    password: 123456

# mybatis
mybatis:
  mapper-locations: classpath:mapper/*mapper.xml
  type-aliases-package: ccom.example.demo.*.entity

注意:

之前都是mysql的库,所以驱动在上面

现在因为数据库的产品不一样,所以驱动类名称放在下面单独配置(有些人真完全不会变通,哎)

3、测试

插入:pg数据库的主键自增mybatis还有点难搞,我们直接配置id插入

  • mysql:

  • pg:

  • 查询:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

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

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com