第50篇-多数据源集成
【Kotlin Spring Boot 4 从零到架构师】第 50 篇多数据源集成本系列定位零基础入门从 Kotlin 语法一路到 Spring Boot 4 高级架构DDD Modulith适合 Java 开发者转型也适合纯新手系统学习。本篇你将学到多数据源的应用场景多数据源配置策略Primary/Qualifier的使用主库PostgreSQL 分析库ClickHouse的双数据源实战学完本篇你将能让 mini-shop 同时连接多个数据库各司其职。一、为什么需要多数据源1.1 典型场景场景数据源 A数据源 B读写分离主库写从库读业务 分析PostgreSQL业务ClickHouse统计分析多租户主租户库独立租户库迁移过渡旧数据库新数据库1.2 mini-shop 场景PostgreSQL主库商品、订单、用户 —— 高频读写 ClickHouse分析库订单统计、销量报表 —— 低频大量查询下面是 mini-shop 多数据源架构总览ClickHouse 分析库PostgreSQL 主库mini-shop 应用JPA / PrimaryNamedParameterJdbcTemplate / Qualifier业务 Service分析 AnalyticsService订单表商品表用户表订单统计销量报表二、配置两个数据源2.1 添加依赖dependencies{implementation(org.springframework.boot:spring-boot-starter-data-jpa)runtimeOnly(org.postgresql:postgresql)runtimeOnly(com.clickhouse:clickhouse-jdbc:0.7.0)}2.2 application.ymlspring:datasource:# 主数据源PostgreSQL—— 业务数据url:jdbc:postgresql://localhost:5432/mini_shopusername:postgrespassword:postgres123driver-class-name:org.postgresql.Driverhikari:pool-name:PrimaryPool# 自定义分析数据源配置analytics:datasource:url:jdbc:clickhouse://localhost:8123/mini_shop_analyticsusername:defaultpassword:driver-class-name:com.clickhouse.jdbc.ClickHouseDriverhikari:pool-name:AnalyticsPoolmaximum-pool-size:52.3 主数据源配置packagecom.example.minishop.configimportorg.springframework.boot.autoconfigure.jdbc.DataSourcePropertiesimportorg.springframework.boot.context.properties.ConfigurationPropertiesimportorg.springframework.boot.jdbc.autoconfigure.DataSourcePropertiesasBootDataSourcePropertiesimportorg.springframework.context.annotation.Beanimportorg.springframework.context.annotation.Configurationimportorg.springframework.context.annotation.Primaryimportorg.springframework.data.jpa.repository.config.EnableJpaRepositoriesimportjavax.sql.DataSourceConfigurationEnableJpaRepositories(basePackages[com.example.minishop.product,com.example.minishop.order,com.example.minishop.user],entityManagerFactoryRefprimaryEntityManagerFactory,transactionManagerRefprimaryTransactionManager)classPrimaryDataSourceConfig{BeanPrimaryConfigurationProperties(spring.datasource)funprimaryDataSourceProperties():DataSourceProperties{returnDataSourceProperties()}BeanPrimaryfunprimaryDataSource():DataSource{returnprimaryDataSourceProperties().initializeDataSourceBuilder().build()}}2.4 分析数据源配置packagecom.example.minishop.configimportorg.springframework.boot.context.properties.ConfigurationPropertiesimportorg.springframework.context.annotation.Beanimportorg.springframework.context.annotation.Configurationimportorg.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplateimportjavax.sql.DataSourceConfigurationclassAnalyticsDataSourceConfig{BeanConfigurationProperties(spring.analytics.datasource)funanalyticsDataSourceProperties():DataSourceProperties{returnDataSourceProperties()}Bean(analyticsDataSource)funanalyticsDataSource():DataSource{returnanalyticsDataSourceProperties().initializeDataSourceBuilder().build()}Bean(analyticsJdbcTemplate)funanalyticsJdbcTemplate(Qualifier(analyticsDataSource)dataSource:DataSource):NamedParameterJdbcTemplate{returnNamedParameterJdbcTemplate(dataSource)}}2.5 使用分析数据源ServiceclassAnalyticsService(Qualifier(analyticsJdbcTemplate)privatevalanalyticsJdbc:NamedParameterJdbcTemplate){/** * 查询每日销售统计 */fungetDailySalesStats(startDate:String,endDate:String):ListDailySalesStat{valsql SELECT toDate(created_at) AS date, count() AS order_count, sum(total_amount) AS total_revenue, avg(total_amount) AS avg_order_value FROM orders WHERE created_at BETWEEN :start AND :end AND status PAID GROUP BY date ORDER BY date .trimIndent()valparamsmapOf(starttostartDate,endtoendDate)returnanalyticsJdbc.query(sql,params){rs,_-DailySalesStat(daters.getString(date),orderCountrs.getLong(order_count),totalRevenuers.getBigDecimal(total_revenue),avgOrderValuers.getBigDecimal(avg_order_value))}}}dataclassDailySalesStat(valdate:String,valorderCount:Long,valtotalRevenue:BigDecimal,valavgOrderValue:BigDecimal)下面是双数据源配置与注入的完整流程Service 层Repository 层Bean 定义配置层application.ymlspring.datasource (PG)spring.analytics.datasource (CH)PrimaryDataSourceConfigConfigurationPropertiesPrimaryAnalyticsDataSourceConfigConfigurationPropertiesprimaryDataSource (PG)PrimaryanalyticsDataSource (CH)analyticsJdbcTemplateNamedParameterJdbcTemplateEnableJpaRepositoriesproduct / order / userOrderService自动注入 PrimaryAnalyticsServiceQualifier 指定三、关键注意事项3.1 Primary 的作用当 Spring 容器中有多个DataSourceBean 时Primary标记的 Bean 是默认选择。Liquibase、Spring Data JPA 自动配置默认会用Primary的数据源。BeanPrimary// ← 主数据源Spring Boot 自动配置用这个funprimaryDataSource():DataSource{...}3.2 Qualifier 精确指定// 不用 Primary 时必须用 Qualifier 指定ServiceclassAnalyticsService(Qualifier(analyticsDataSource)// ← 精确指定分析数据源privatevalanalyticsDataSource:DataSource)3.3 ClickHouse autoCommit 陷阱ClickHouse 的 JDBC 驱动要求autoCommit true与 PostgreSQL 不同spring:analytics:datasource:hikari:auto-commit:true# ClickHouse 必须为 true3.4 Liquibase 只在主数据源spring:liquibase:change-log:classpath:db/changelog/db.changelog-master.yaml# Liquibase 默认用 Primary 数据源不需要额外配置四、Primary vs Qualifier 决策方式特点场景Primary全局默认选择主数据源90% 用这个Qualifier(name)精确指定分析数据源、特定场景原则主数据源用Primary其他数据源用Qualifier显式注入。下面是数据源选择决策流程图是否是否是否需要注入 DataSource只有一个 DataSource BeanSpring 自动注入无需额外注解该数据源是主业务数据源标记 Primary全局默认选择注入点明确知道要哪个数据源使用 Qualifier(beanName)精确指定编译报错NoUniqueBeanDefinitionExceptionLiquibase / JPA 自动配置默认使用 Primary手动指定注入如 analyticsDataSource本篇小结知识点核心内容多数据源业务库 分析库 / 读写分离Primary标记主数据源默认选择Qualifier精确指定注入哪个数据源ConfigurationProperties绑定各数据源配置EnableJpaRepositories指定 Repository 用哪个数据源NamedParameterJdbcTemplate非 JPA 的数据源操作ClickHouse autoCommit必须为trueLiquibase只在主数据源下篇预告第 51 篇Kotlin 协程在 Spring Boot 中的应用Spring Boot 4 支持协程 Controller下一篇学习suspend函数在 Web 层、数据访问层的实际应用以及虚拟线程的对比。如果本篇内容对你有帮助欢迎点赞收藏有任何疑问欢迎在评论区交流。

相关新闻

Vue3+Element Plus全局图标管理:从手动引入到自动化方案实战

Vue3+Element Plus全局图标管理:从手动引入到自动化方案实战

1. 项目概述:为什么我们需要全局管理图标? 在Vue3和Element Plus的项目里,图标的使用频率高得惊人。从导航菜单的箭头、按钮里的加号,到表格的操作栏、表单的状态提示,几乎无处不在。早期开发时,我们可能习…

2026/10/18 12:52:19 阅读更多 →
ANSYS APDL中ASEL命令详解:从基础语法到高级应用场景

ANSYS APDL中ASEL命令详解:从基础语法到高级应用场景

1. 项目概述:为什么ASEL命令是APDL建模的“手术刀”?在ANSYS APDL这个以命令流为核心驱动的经典仿真环境中,每一个建模、加载、求解和后处理动作,本质上都是对数据库中几何与有限元对象的精准“选取”与“操作”。而ASEL命令&…

2026/10/18 23:13:48 阅读更多 →
Android Studio打包APK全流程详解:从签名配置到优化发布

Android Studio打包APK全流程详解:从签名配置到优化发布

1. 项目概述:从代码到可安装应用的关键一跃对于每一位Android开发者来说,无论你是刚入门的新手,还是已经写过几万行代码的老手,最终都需要面对同一个问题:如何把自己的心血结晶——那一行行代码、一个个界面——变成一…

2026/10/16 15:24:04 阅读更多 →

最新新闻

Android自定义SeekBar:图片背景与图片进度的实现方案与避坑指南

Android自定义SeekBar:图片背景与图片进度的实现方案与避坑指南

简介:面向Android开发者的SeekBar定制方案资源包,以图片替换系统原生样式,解决默认SeekBar外观单一、难以匹配界面整体设计的问题。压缩包内是一个完整的Eclipse工程示例,演示如何继承SeekBar并编写MySeekBar类,在attr…

2026/10/19 2:21:37 阅读更多 →
匹配滤波与脉冲压缩:从信噪比最大化到MATLAB仿真避坑

匹配滤波与脉冲压缩:从信噪比最大化到MATLAB仿真避坑

简介:这是一份面向雷达信号处理、数字信号处理学习者的Matlab仿真与推导资料,核心围绕线性调频(LFM)信号匹配滤波,系统讲解增益和归一化系数的来龙去脉。作者先分别推导信号和白噪声通过匹配滤波后的增益公式&#xff…

2026/10/19 2:21:37 阅读更多 →
基于RK3588的边缘AI婴儿监护系统:多模态融合与工程实践

基于RK3588的边缘AI婴儿监护系统:多模态融合与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:21:37 阅读更多 →
Codex 0.105.0语音编程实测:按住空格说话让AI直接写代码

Codex 0.105.0语音编程实测:按住空格说话让AI直接写代码

作为一个常年在终端里干活的人,我对"命令行工具又更新了"这种消息本来已经麻木了。但这次 Codex 0.105.0 的更新确实让我多看了两眼:按住空格键,对着终端说话,让它直接把代码写出来。听起来像demo噱头,但真正…

2026/10/19 2:21:37 阅读更多 →
专科生论文降AIGC检测全攻略:从查重到AI痕迹的实战方法

专科生论文降AIGC检测全攻略:从查重到AI痕迹的实战方法

查重率10%,AIGC疑似度91%。A同学拿着检测报告坐在我面前时,表情比论文答辩还沉重。导师的话很直接:要么把AI痕迹降下来,要么别进盲审。这不是个例。最近几个月,找我咨询论文降重的人里,专科生比例明显上升&…

2026/10/19 2:21:37 阅读更多 →
PyCharm 安装激活全流程避坑指南:从版本选择到环境配置

PyCharm 安装激活全流程避坑指南:从版本选择到环境配置

简介:面向初学Python编程语言或需要重新配置开发环境的人群,这份PyCharm安装教程以Word文档形式,完整梳理了从获取安装包、安装选项配置到激活授权的整个操作链路。文档采用分步骤讲解,先介绍在浏览器搜索入口找到下载页面&#x…

2026/10/19 2:20:36 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →