基于SpringBoot多数据源解决方案

最近在学习SpringBoot的时候,需要同时用两个不同的数据库连接服务,在网上学习了之后,下文以连接一个MySQL数据库和一个SqlServer数据库为例。

配置数据源连接信息

在配置文件中,配置对应的数据库连接信息,相比于单数据源时连接信息的url属性在多数据源时应该为jdbc-url,请注意下图红色部分:

application.yml

复制代码
spring:
	datasource:
        webproject:
          type: mysql
          driver-class-name: com.mysql.cj.jdbc.Driver
          jdbc-url: jdbc:mysql://localhost:3306/webproject?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
          username: 
          password: 
        workcontent:
          type: sqlServer
          driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
          jdbc-url: jdbc:sqlserver://localhost:1433;databaseName=myDatabase;encrypt=true;trustServerCertificate=true;characterEncoding=utf8;
          username: 
          password: 

Maven配置数据库驱动

由于新版的官方Sqlserver驱动不支持TLSv1, TLSv1.1,我选择了较老的数据库驱动程序。

复制代码
<!--    sqlserver驱动    -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>7.4.1.jre11</version>
</dependency>
<!--	MYSQL驱动	-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

创建数据源配置类

以下文中的 WorkContentDataSourceConfig 为例,基本的流程如下:

配置类声明

配置要该数据源相关的Mapper所在的的包扫描和要注入的Sql工厂实例

创建数据源DataSource

@ConfigurationProperties 用于注入application.yml中配置的数据库连接信息

@Primary 默认指定当前数据库,多数据源下需要配置@Primary,不然SpringBoot会找不到数据源注入,后续步骤最好也加上@Primary

创建Sql工厂,注册DataSource

@Qualifier 用于选择注入的bean对象

创建事务管理器

创建Sql模版对象

具体配置类信息如下:

复制代码
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
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.boot.jdbc.DataSourceBuilder;
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.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @author yamu
 * @version 1.0
 * @description 工作库
 * @date 2025/1/23 10:49
 */
@Configuration
@MapperScan(basePackages = {"org.cqw.baseproject.dao.workcontent"},
        sqlSessionFactoryRef = "workContentSqlSessionFactory")
public class WorkContentDataSourceConfig {

    @Bean(name = "workContentDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.workcontent")
    @Primary
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "workContentSqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("workContentDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().
                getResources("classpath:mapper/workcontent/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "workContentTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("workContentDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "workContentSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("workContentSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
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.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @author yamu
 * @version 1.0
 * @description 项目库	
 * @date 2025/1/23 10:49
 */
@Configuration
@MapperScan(basePackages = {"org.cqw.baseproject.dao.webproject"}, sqlSessionFactoryRef = "webProjectSqlSessionFactory")
public class WebProjectDataSourceConfig {

    @Bean(name = "webProjectDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.webproject")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "webProjectSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("webProjectDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/webproject/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "webProjectTransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("webProjectDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "webProjectSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("webProjectSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

创建实体

实体所在的包需要和创建配置类中的第一步的 配置类声明的@MapperScan的basePackages值相对应。

复制代码
package org.cqw.baseproject.dao.webproject;
@Repository
public interface FunctionMenuDao {
    FunctionMenu queryById(int id);
    List<FunctionMenu> queryAll();
}

创建Mapper

由于有多个数据源,所以在/resources/mapper里面需要区分不同的数据库(即创建不同的文件夹,每个数据源扫描自己的mapper

.xml文件),如下图所示,注意和第三步创建Sql工厂,注册DataSourceSqlSessionFactorybean.setMapperLocations()里面的路径对应上,对于Mapper.xml里面的配置这里就不具体说明了。

FunctionMenuMapper.xml

复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.cqw.baseproject.dao.webproject.FunctionMenuDao">
    <select id="queryById" resultType="org.cqw.baseproject.entity.FunctionMenu">
           SELECT * FROM FunctionMenu WHERE id = #{id}
    </select>
    <select id="queryAll" resultType="org.cqw.baseproject.entity.FunctionMenu">
            SELECT * FROM FunctionMenu WHERE isDel = '0' AND status = '1' ORDER BY depth, id
    </select>
</mapper>

测试

关于 Service 和 ServiceImpl 这里就省略了

FunctionMenuController

复制代码
@RestController
@RequestMapping("/functionMenu")
public class FunctionMenuController {
    @Autowired
    public FunctionMenuService functionMenuService;

    @GetMapping("getAllMenuList")
    public String getAllMenuList() {
        var data = functionMenuService.getAllMenuList();
        return R.success(data);//消息响应
    }
}

结果:

复制代码
    public FunctionMenuService functionMenuService;

    @GetMapping("getAllMenuList")
    public String getAllMenuList() {
        var data = functionMenuService.getAllMenuList();
        return R.success(data);//消息响应
    }
}

结果:

相关推荐
一颗知足的心6 分钟前
Go语言之路————指针、结构体、方法
开发语言·后端·golang
北执南念14 分钟前
项目代码生成工具
java
中国lanwp20 分钟前
springboot logback 默认加载配置文件顺序
java·spring boot·logback
cherishSpring31 分钟前
在windows使用docker打包springboot项目镜像并上传到阿里云
spring boot·docker·容器
苹果酱05671 小时前
【Azure Redis 缓存】在Azure Redis中,如何限制只允许Azure App Service访问?
java·vue.js·spring boot·mysql·课程设计
Java致死1 小时前
单例设计模式
java·单例模式·设计模式
胡子发芽1 小时前
请详细解释Java中的线程池(ThreadPoolExecutor)的工作原理,并说明如何自定义线程池的拒绝策略
java
沫夕残雪1 小时前
Tomcat的安装与配置
java·tomcat
Rabbb2 小时前
C# JSON属性排序、比较 Newtonsoft.Json
后端
蓝易云2 小时前
在Linux、CentOS7中设置shell脚本开机自启动服务
前端·后端·centos