dynamic-datasource动态数据源学习

article/2025/10/2 12:55:18

学习链接

spring整合mybatis的核心思路 & 数据源动态切换 & 多数据源事务控制 - 自己的链接(本篇文章的上篇)

Mybatisplus生成代码配置 & p6spy打印sql & mybatis日志打印 & mybatisplus用法

dynamic-datasource-spring-boot-starter 的gitee地址
dynamic-datasource官方文档(收费)(使用自己的qq登录即可)

SpringBoot多数据源

【Java多数据源实现教程】实现动态数据源、多数据源切换方式

springboot多数据源使用
SpringBoot实现多数据源(六)【dynamic-datasource 多数据源组件】
【Java多数据源实现教程】实现动态数据源、多数据源切换方式
Springboot多数据源配置详解
SpringBoot多数据源配置

基础介绍

简介

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

其支持 Jdk 1.7+, SpringBoot 1.4.x 1.5.x 2.x.x。

特性

  • 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
  • 支持数据库敏感配置信息 加密 ENC()。
  • 支持每个数据库独立初始化表结构schema和数据库database。
  • 支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)。
  • 支持 自定义注解 ,需继承@DS(3.2.0+)。
  • 提供并简化对Druid,HikariCp,BeeCp,Dbcp2的快速集成。
  • 提供对Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等组件的集成方案。
  • 提供 自定义数据源来源 方案(如全从数据库加载)。
  • 提供项目启动后 动态增加移除数据源 方案。
  • 提供Mybatis环境下的 纯读写分离 方案。
  • 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
  • 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
  • 提供 基于seata的分布式事务方案
  • 提供 本地多数据源事务方案(不能和原生spring事务混用)

约定

  • 本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
  • 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称相同组名称的数据源会放在一个组下
  • 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换
  • 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
  • 方法上的注解优先于类上注解
  • DS支持继承抽象类上的DS,暂不支持继承接口上的DS

使用方法

1. 引入dynamic-datasource-spring-boot-starter

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>${version}</version>
</dependency>

2. 配置数据源

以下会配置一个默认库master,一个组slave(组名)下有两个子库slave_1(组名为slave组下的数据源名称slave_1) 和 slave_2(组名为slave组下的数据源名称slave_2)

spring:datasource:dynamic:primary: master #设置默认的数据源或者数据源组,默认值即为masterstrict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源datasource:master:url: jdbc:mysql://xx.xx.xx.xx:3306/dynamicusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置slave_1:url: jdbc:mysql://xx.xx.xx.xx:3307/dynamicusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverslave_2:url: ENC(xxxxx) # 内置加密,使用请查看详细文档username: ENC(xxxxx)password: ENC(xxxxx)driver-class-name: com.mysql.jdbc.Driver#......省略

其它配置示例

# 多主多从                      纯粹多库(记得设置primary)                   混合配置
spring:                               spring:                               spring:datasource:                           datasource:                           datasource:dynamic:                              dynamic:                              dynamic:datasource:                           datasource:                           datasource:master_1:                             mysql:                                master:master_2:                             oracle:                               slave_1:slave_1:                              sqlserver:                            slave_2:slave_2:                              postgresql:                           oracle_1:slave_3:                              h2:                                   oracle_2:

3. 使用 @DS 切换数据源

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解
在这里插入图片描述

@Service
@DS("slave")
public class UserServiceImpl implements UserService {@Autowiredprivate JdbcTemplate jdbcTemplate;public List selectAll() {return  jdbcTemplate.queryForList("select * from user");}@Override@DS("slave_1")public List selectByCondition() {return  jdbcTemplate.queryForList("select * from user where age >10");}
}

数据源切换示例

简单演示下使用@DS注解,切换指定的数据源

准备数据库

准备2个数据库,一个m_db(作为主库),一个s_db(作为从库),这2个数据库中都有一张account表,表中仅有id和nick_name字段

CREATE TABLE `account` (`id` int(11) NOT NULL AUTO_INCREMENT,`nick_name` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

pom.xml

导入mybatis-plus(不一定要用mybatis-plus,只是因为懒得自己写mapper.xml文件) 和 dynamic-datasource 的依赖

<?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.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><!--项目GAV坐标--><groupId>com.zzhua</groupId><artifactId>sdynamic-datasource-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-demo</name><description>Demo project for Spring Boot</description><!--版本--><properties><java.version>1.8</java.version></properties><dependencies><!--web启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.3</version></dependency><dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.9.1</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.1</version></dependency><!--swagger2依赖--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version> 2.7.0</version></dependency><!--swagger-ui第三方依赖--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--打开提示--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!--热部署--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><!--测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml

#spring:
#  datasource:
#    type: com.zaxxer.hikari.HikariDataSource
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    url: jdbc:mysql://127.0.0.1:3306/m_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
#    username: root
#    password: rootspring:datasource:dynamic:primary: masterstrict: truedatasource:master:url: jdbc:mysql://127.0.0.1:3306/m_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverhikari:min-idle: 2max-pool-size: 5# 使用下划线, 下划线前面的是组名,整个为数据源标识(若@DS中使用组名, 则会负载均衡该组名下的所有数据源)slave_1:url: jdbc:mysql://127.0.0.1:3306/s_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:mapper-locations: classpath:mapper/**.xml

SpringbootDemoApplication

开启mybatis的mapper接口扫描

@SpringBootApplication
@MapperScan("com.zzhua.mapper")
public class SpringbootDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootDemoApplication.class, args);}}

AccountController

@RestController
@RequestMapping("/account")
public class AccountController {@Autowiredprivate IAccountService accountService;@RequestMapping("createAccount")public Object createAccount(@RequestParam("nickName") String nickName) {Account account = new Account();account.setNickName(nickName);accountService.addAccount(account);return "ok";}@RequestMapping("getAccounts")public List<Account> getAccounts() {return accountService.findAll();}}

IAccountService

public interface IAccountService extends IService<Account> {void addAccount(Account account);List<Account> findAll();}

AccountServiceImpl

@DS("master") // 方法中的@DS注解优先
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements IAccountService {@Overridepublic void addAccount(Account account) {this.save(account);}@Override@DS("slave") // 填写组名, 会负载均衡// @DS("slave_1")public List<Account> findAll() {return this.list();}}

AccountMapper

public interface AccountMapper extends BaseMapper<Account> {}

AccountMapper.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="com.zzhua.mapper.AccountMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="com.zzhua.entity.Account"><id column="id" property="id" /><result column="nick_name" property="nickName" /></resultMap><!-- 通用查询结果列 --><sql id="Base_Column_List">id, nick_name</sql></mapper>

测试

访问:http://localhost:8080/account/createAccount?nickName=m1,发现数据插入到了m_db数据库中
访问:http://localhost:8080/account/getAccounts,发现查询的是s_db数据库


http://chatgpt.dhexx.cn/article/CUZNpgFc.shtml

相关文章

什么是 Dynatrace 的 Largest Contentful Paint

Dynatrace 多维分析使 Web 开发人员能够沿多个过滤维度分析浏览器监控执行情况。 多维分析页面以图表形式显示选定时间范围内的性能、可用性和错误计数。 可以选择较短的分析范围并以散点图和列表格式查看单个数据点。 页面顶部显示长期&#xff08;时间序列&#xff09;数据…

使用 Dynatrace 对 Node.js 应用的性能数据进行分析

JavaScript Storefront 应用程序的性能问题的表现形式有多种&#xff0c;最典型的是响应时间(response time)的恶化&#xff0c;甚至由于资源耗尽导致的网站完全宕机。 由于 JavaScript Storefront 涉及许多组件&#xff0c;因此确定性能问题的根源可能具有挑战性&#xff0c;如…

dynatrace 详解

dynaTrace Ajax&#xff1a;前端性能分析利器 谢 菊, 性能分析工程师, IBM 谢菊&#xff0c;IBM 中国软件开发中心&#xff08;CDL&#xff09;Lotus 部门的软件性能分析工程师&#xff0c;具有多个产品的性能测试经验&#xff0c;如IBM Portal Accelerator 和IBM Docs。目前正…

dynaTrace Ajax:前端性能分析利器

什么是 dynaTrace Ajax 随着 jQuery、Dojo、YUI 等框架的兴起让构建 Web2.0 应用更加容易&#xff0c;但随之带来的定位等应用问题也越来越难&#xff0c;尤其是与性能相关的。dynaTrace Ajax Edition 是一个强大的底层追踪、前端性能分析工具&#xff0c;该工具不仅能够记录浏…

监控方法基本套路

监控方法基本套路 性能测试监控方法基本套路 1、传统OS定位方法&#xff1a; 通过CPU&#xff0c;内存&#xff0c;IO&#xff0c;网络等指标初步确定问题根据问题进一步确定进程的PID根据进程PID&#xff0c;确定到线程基本TID根据线程的Dump确定堆栈信息根据堆栈信息定位到…

Dynatrace系列之- 如何发现和分析问题

Dynatrace系列之- 如何发现和分析问题 Dynatrace用Problem(问题)表示异常情况&#xff0c;即偏离了正常行为或状态。例如某个服务速度变慢或某个用户登录应用速度变慢。每当检测到问题时&#xff0c;Dynatrace都会引发一个特定的problem event(问题事件)来表示此类异常。 请注…

网址和URL之间的区别:什么是RUI、RUL、URN

调用Web地址是普通的一个问题。一般这种情况&#xff0c;大家都会说&#xff0c;将“URL”放到浏览器中。这里提到的URL &#xff0c;其实不是一个URL &#xff0c;是网址的意思。URI 是统一资源标识符&#xff0c;而 URL 是统一资源定位符。因此&#xff0c;笼统地说&#xff…

146. LRU 缓存机制

LRU 缓存机制 运用你所掌握的数据结构&#xff0c;设计和实现一个 LRU (最近最少使用) 缓存机制 。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字…

物理读之LRU(最近最少被使用)的深入解析 (解释LRU_FLAG的含义)

物理读之LRU&#xff08;最近最少被使用&#xff09;的深入解析 转载请注明出处&#xff1a; http://blog.csdn.net/guoyjoe/article/details/38264883 一组LRU链表包括LRU主链&#xff0c;LRU辅助链&#xff0c;LRUW主链&#xff0c;LRUW辅助链&#xff0c;称为一个WorkSet(…

LRU(最近最少使用)缓存机制

title: LRU缓存机制 categories: 操作系统 tags: 操作系统LRUOS计算机知识 LRU(最近最少使用)缓存机制 LRU&#xff1a;最近最少使用缓存机制 其设计的原则依据&#xff1a;如果一个数据在最近一段时间没有被访问到&#xff0c;那么在将来它被访问的可能性也很小。也就是…

LRU简单实现-了解一下?

LRU 算法 LRU 是一种作为缓存的算法&#xff0c;像 CPU 缓存&#xff0c;数据库缓存&#xff0c;浏览器缓存。以及在移动端开发时的图片安缓存&#xff0c;采用 LRU 缓存策略的应用很广泛。在面试中也是常常考察的一个点。当然也有其他缓存方法&#xff0c;常见的策略有三种&a…

LRU总结

文章目录 [146. LRU 缓存机制](https://leetcode-cn.com/problems/lru-cache/)ACM模式LRU 在 MySQL 中的应用LRU 在 Redis 中的应用面试官&#xff1a;来&#xff0c;手写一个线程安全并且可以设置过期时间的LRU缓存 146. LRU 缓存机制 力扣原题 class Node{public int key;pu…

html ur是什么意思_url是什么意思?

实际上,我们在使用互联网的过程中,其中有许多东西都是只会用,而不知道它到底是啥名字,看见了也不理解它是做什么的,比如今天我将和大家说的URL,实际上就是我们在互联网生活中非常常见的一个东西。 web前端学习:打造全网web前端全栈资料库(总目录)看完学的更快,掌握的…

LRU 缓存(Java)

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回 -1…

LRU算法的理解,终于懂了

https://blog.csdn.net/luoweifu/article/details/8297084 以上是让我看明白的博客链接。 下面是我自己的理解&#xff0c;比如下面这道题&#xff1a; 可以这么来看&#xff0c;有一个容量为6的容器&#xff0c;每次放进去一个有编号的球&#xff0c;如果容器中有相同编号…

LRU缓存

一、什么是LRU算法 LRU&#xff0c;Least Recently Used算法&#xff0c;即一种缓存淘汰策略。 计算机的缓存容量有限&#xff0c;若缓存满了则需要删除一些内容&#xff0c;给新的缓存腾出空间&#xff0c;但问题是要删除哪些内容呢&#xff1f;当然是把用的少的缓存删掉&am…

【网络】HTTP 协议中 URI 和 URL 有什么区别?

HTTP定义 超文本传输协议&#xff08;Hyper Text Transfer Protocol&#xff0c;HTTP&#xff09;是一个简单的请求-响应协议&#xff0c;它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出 HTTP是用…

LRU缓存机制,你想知道的这里都有

概述 LRU是Least Recently Used的缩写&#xff0c;译为最近最少使用。它的理论基础为 “最近使用的数据会在未来一段时期内仍然被使用&#xff0c;已经很久没有使用的数据大概率在未来很长一段时间仍然不会被使用” 由于该思想非常契合业务场景 &#xff0c;并且可以解决很多实…

LRU简单实现-了解一下

LRU 算法 LRU 是一种作为缓存的算法&#xff0c;像 CPU 缓存&#xff0c;数据库缓存&#xff0c;浏览器缓存。以及在移动端开发时的图片安缓存&#xff0c;采用 LRU 缓存策略的应用很广泛。在面试中也是常常考察的一个点。当然也有其他缓存方法&#xff0c;常见的策略有三种&a…

数据分析:RFM模型

补充&#xff1a; RFM分析方法&#xff1a;如何对用户按价值分类 深入解读和应用RFM分析方法(模型) 深入解读RFM模型-实战应用干货 转载自&#xff1a; 接地气的陈老师|作者 接地气学堂|来源&#xff1a;https://mp.weixin.qq.com/s/00vJPb9xqx4NL5Y5cPDXsw 问他咋做数据分…