基于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);//消息响应
    }
}

结果:

相关推荐
人生在勤,不索何获-白大侠几秒前
day17——Java集合进阶(Collections、Map)
java·开发语言
程序员小羊!12 分钟前
Java教程:JavaWeb ---MySQL高级
java·开发语言·mysql
白仑色20 分钟前
Spring Boot 多环境配置详解
java·spring boot·后端·微服务架构·配置管理
懒斌20 分钟前
linux驱动程序
后端
超级小忍22 分钟前
在 Spring Boot 中优化长轮询(Long Polling)连接频繁建立销毁问题
java·spring boot·后端
David爱编程26 分钟前
Java 中 Integer 为什么不是万能的 int 替代品?
java·后端
阿宝想会飞27 分钟前
easyExcel多出大量数据方法
后端
自由的疯28 分钟前
基于 Java POI 实现动态列 Excel 导出的通用方法
后端
老马啸西风28 分钟前
个人网站一键引入免费开关评论功能 giscus
java
自由的疯28 分钟前
Java 利用 Apache POI 实现多模板 Word 文档生成(补充:模板文档为复杂表单的处理办法)
后端