0

0

springboot如何配置多数据源

无忌哥哥

无忌哥哥

发布时间:2018-07-20 11:22:28

|

2497人浏览过

|

来源于php中文网

原创

摘要: 目前项目中持久化框架使用是mybatis,经过分析后不难发现,多数据源配置需要解决两个问题,一个是由原先的spring经典方式切换到了springboot方式下,多数据源如何配置?有无太大变化?另一个是怎样将多数据源与mybatis的配置关联起来?

前言

最近迫于项目需要,笔者踏上了springboot多数据源的配置之旅。之前笔者配置过spring的动态多数据源切换,当时使用的是jdbc template。

目前项目中持久化框架使用是mybatis,经过分析后不难发现,多数据源配置需要解决两个问题,一个是由原先的spring经典方式切换到了springboot方式下,多数据源如何配置?有无太大变化?另一个是怎样将多数据源与mybatis的配置关联起来?

不妨先来看下,单数据源下mybatis如何配置的?

单数据源示例

首先要声明一点,项目只是依赖单个数据源时,如果你不介意springboot帮你做事的话,那么恭喜你,你省事儿了!你只需要在项目的属性文件中添加数据源的相关属性配置,springboot会“免费”提供给你一个数据源使用,默认采用的是tomcat jdbc connection pool。

当然你可以拒绝springboot的好意,如果你依赖第三方的连接池技术,你可以配置自己的数据源,那么springboot检测到你自己定义了DataSource后,就不会自动配置数据源了。

笔者不能拒绝springboot的好意,所以仅在项目的application.properties中添加了如下属性:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=18800
然后笔者创建了一个专门用于配置mybatis的类,如下:
@Configuration
public class MybatisSpringConfig {
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage("demo.model");
return factoryBean.getObject();
}
[[[@Bean](http://my.oschina.net/bean)](http://my.oschina.net/bean)](http://my.oschina.net/bean)
public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    mapperScannerConfigurer.setBasePackage("demo.repository");
    return mapperScannerConfigurer;
}
}

没错,mybatis在spring中就是可以通过如此的简练配置进而正常工作起来。你无需刻意地去创建mybatis的配置文件,无需刻意地去注册mapper接口及指定对应xml文件的位置,这完全得益于mybatis-spring,它就像一个“粘合剂”,可以很方便地将mybatis和spring“粘合”在一起。

MyBatis-Spring的配置步骤

不妨先来说下mybatis-spring配置的一般步骤:

  1. 配置数据源DataSource的Bean。

  2. 使用DataSource配置事务管理器。

  3. 使用DataSource配置SqlSessionFactory的Bean。

  4. 配置MapperScannerConfigurer的Bean。

这里要求配置事务管理器和SqlSessionFactory的数据源必须是同一个,否则事务管理不起作用。配置MapperScannerConfigurer的目的是自动扫描mapper接口所在的包,自动帮你将mapper接口注册为Bean(代理生成接口的实现类),你就可以直接拿来依赖注入了,建议将mapper接口及其对应的xml文件放在同一个包下,这样的话你无需在SqlSessionFactory里指定xml文件的位置了。

OK,到此对比我上面贴出的配置类内容,你可能会发现笔者怎么少了几步?感谢springboot,因为它自动配置了一个DataSource,同时它还自动配置了一个事务管理器。所以笔者只配置了SqlSessionFactory和MapperScannerConfigurer。

当然如果看到这里你仍然“执意”要配置自己的数据源,参照下面的多数据源配置说明,抽出来多个中的一个就可以实现自定义单数据源的配置了。

多数据源示例

经过上面单数据源的示例,可以说当我们切换到springboot的方式下写代码时,springboot为我们带来了很大的便利,还不影响我们自定义,所以笔者认为,没用使用springboot之前,无论你使用spring怎样的配置,使用springboot之后,不会有阻碍,甚至会比原来更快!

简单说下需要多数据源的场景,笔者参照了一下其他的文章,绝大部分的需要来自于数据库主从方式或读写分离。那么就按照master和slave两个数据源,直接贴出数据源的配置类。

  • application.properties

datasource.master.url=jdbc:mysql://localhost:3306/master
datasource.master.username=root
datasource.master.password=root
datasource.master.driver-class-name=com.mysql.jdbc.Driver
datasource.master.max-idle=10
datasource.master.max-wait=10000
datasource.master.min-idle=5
datasource.master.initial-size=5
datasource.master.validation-query=SELECT 1
datasource.master.test-on-borrow=false
datasource.master.test-while-idle=true
datasource.master.time-between-eviction-runs-millis=18800
datasource.slave.url=jdbc:mysql://localhost:3306/slave
datasource.slave.username=root
datasource.slave.password=root
datasource.slave.driver-class-name=com.mysql.jdbc.Driver
datasource.slave.max-idle=10
datasource.slave.max-wait=10000
datasource.slave.min-idle=5
datasource.slave.initial-size=5
datasource.slave.validation-query=SELECT 1
datasource.slave.test-on-borrow=false
datasource.slave.test-while-idle=true
datasource.slave.time-between-eviction-runs-millis=18800
  • master数据源

@Configuration
public class MasterConfig {
[[[@Primary](http://my.oschina.net/primary)](http://my.oschina.net/primary)](http://my.oschina.net/primary)
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "datasource.master")
public DataSource dataSource() {
    return DataSourceBuilder.create().build();
}

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

  • slave数据源

@Configuration
public class SlaveConfig {
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "datasource.slave")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build(){
    }
    @Bean(name = "slaveTransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

不难看出两个数据源的配置步骤吧:

  1. 在属性文件中配置两个数据源需要用到的属性值,注意起个好点的前缀名称。

    PaperFake
    PaperFake

    AI写论文

    下载
  2. 构建两个数据源的配置类,当然这不是必须的,愿意堆在一个配置类中未尝不可。

  3. 配置类中,配置DataSource的Bean,记得起个能够标识的name!

  4. 配置两个数据源各自对应的事务管理器,别嫌麻烦,否则会给自己埋坑里,记得起个能够标识的name!

配置DataSource时,利用@ConfigurationProperties(prefix = "xxx.xxx")可以依靠指定的前缀,在诸多的属性值中“挑选”出数据源依赖的属性,进而完成数据源的构建。

当自己定义了DataSource后,springboot就会取消自动配置的动作了。为了各司其职,为每个数据源配置各自的事务管理器,springboot自然也会取消自动配置事务管理器的动作。由于是多个数据源和多个事务管理器,都是一个类型的,你要是不起个区别的名字,任谁都分辨不出来吧?

@Primary 有什么作用呢?简单地说,当有两个同一类型的Bean,依赖注入时你没有指定name,正常情况下会报错,有两个你要的Bean,识别不了。但是 @Primary 相当于指定这个Bean为默认的,如果你没有指定name,就采用 @Primary 标识的Bean。

OK,两个数据源的配置配好了,还需要配置各自的Mybatis来进行持久化的操作。

MyBatis-Spring相关配置

  • mybatis for master

@Configuration
@MapperScan(basePackages = {"demo.repository.master"}, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterConfig {
    @Primary
    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "datasource.master")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
@Primary
@Bean(name = "masterTransactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}
@Primary
@Bean(name = "masterSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource);
    factoryBean.setTypeAliasesPackage("demo.model");
    return factoryBean.getObject();
}
}

  • mybatis for slave

@Configuration
@MapperScan(basePackages = {"demo.repository.slave"}, sqlSessionFactoryRef = "slaveSqlSessionFactory")
public class SlaveConfig {
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "datasource.slave")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "slaveTransactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "slaveSqlSessionFactory")
public SqlSessionFactory basicSqlSessionFactory(@Qualifier("slaveDataSource") DataSource basicDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(basicDataSource);
factoryBean.setTypeAliasesPackage("demo.model");
return factoryBean.getObject();
}
}

这里需要强调几个地方:

  1. 细心人会发现上面的配置类中,少了MapperScannerConfigurer的Bean配置,改用了@MapperScan注解。其实两者的作用是一样的,但是@MapperScan比较新,稍后会做解释为什么它比较新。

  2. 由于两个数据源的原因,引出了两套SqlSessionFactory的配置,所以@MapperScan中需要指明依赖的是哪个SqlSessionFactory,“sqlSessionFactoryRef”对应就是SqlSessionFactory的name属性。

  3. @MapperScan会将扫描的mapper接口代理生成实现类,并自动注册为Bean。由于两个数据源的配置类中都有@MapperScan注解,为了避免造成冲突和排错时的困扰,猛烈提醒,两个数据源的配置,mybatis对应的mapper接口及对应xml文件也构建两套,最好接口名上也做些区分。model类使用同一套倒是没什么影响。所以你会看到上面的配置中,@MapperScan中basePackages指向的是两个包路径。

好了,来解释下@MapperScan为何比较新,并且笔者推荐使用@MapperScan。

首先@MapperScan要求的mybatis-spring版本比较新,说明它是新推出的特性。

其次@MapperScan要比配置MapperScannerConfigurer的Bean要简练的多,代码量上就看得出来。

最后,@MapperScan中的basePackageClasses属性是MapperScannerConfigurer所没有的。并且笔者用到了这个basePackageClasses属性,所以这里强力推荐使用@MapperScan注解。

多聊一些,描述下笔者为何会用到@MapperScan中的basePackageClasses属性吧,况且与上述示例中的basePackages有何区别呢?

上面提到了多数据源的一般场景,笔者的不同。笔者的项目中划分了n个子模块,每个子模块有各自的数据库,现在需要每个子模块共享一个公共信息的数据库。

从代码上来说,由于各个子模块依赖的公共信息数据库-数据源、mapper接口和xml映射文件是相同的,笔者希望将这些类和文件抽离到maven的一个公共module(最后会打包为一个jar文件)中,供其他n个子模块依赖使用,这样可以避免重复代码嘛。

笔者这么做之后,发现配置MapperScannerConfigurer的basePackages找不到mapper接口所在的包路径,因为笔者是在子模块中配置的MapperScannerConfigurer,它自然会在子模块的结构中去寻找指定的包路径,是mapper接口被笔者放到了公共的module中,所以是找不到的!

不过还好在@MapperScan中发现了basePackageClasses属性,它会“接受”你指定的mapper接口的全名。再次提醒,记得把xml映射文件和mapper接口放在一起,mybatis-spring会帮你做关联。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号