目录

  • 前言
  • 框架简介
  • 基本使用
    • 框架说明
    • 与 `springboot` 的整合
      • 数据准备
      • 引入依赖
      • `springboot` 配置文件
      • 启动类
      • 实体类
      • `service` 层
      • `controller` 层
      • 测试
        • `service` 层方法上都没有注解 `@DS`
        • `service` 层方法上加上注解 `@DS` 再测试
      • `@DS` 注解说明

前言

前篇博客介绍了用基本的方式做多数据源,可以应对一般的情况,但是遇到一些复杂的情况就需要扩展下功能了,比如:动态增减数据源、数据源分组,纯粹多库,读写分离一主多从,从其他数据库或者配置中心读取数据源等等。其实就算没有这些需求,使用此款框架实现多数据源也比之前要便捷,快速的多

框架简介

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

文档:https://github.com/baomidou/dynamic-datasource-spring-boot-starter
文档:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter

它跟 mybatis-plus 是一个生态圈里的,都是由苞米豆团队出品,很容易集成 mybatis-plus

基本使用

框架说明

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

springboot 的整合

数据准备

  • springboot 版本:2.0.6.RELEASE
  • mysql 版本:5.7

分别创建数据库 test1,test2,数据库表均为 goods,数据不相同

CREATE TABLE `goods` (`goodsId` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`goodsName` varchar(500) NOT NULL DEFAULT '' COMMENT 'name',`subject` varchar(200) NOT NULL DEFAULT '' COMMENT '标题',`price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '价格',`stock` int(11) NOT NULL DEFAULT '0' COMMENT 'stock',PRIMARY KEY (`goodsId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

test1 数据库数据如下

test2 数据库数据如下

引入依赖

至于其他依赖,不再赘述

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

springboot 配置文件

配置文件详情可以参考官方文档

server.port=8080#设置test1为主数据源
spring.datasource.dynamic.primary=master
#test1主数据源配置
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://127.0.0.1:3306/test1?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
spring.datasource.dynamic.datasource.master.username=root
spring.datasource.dynamic.datasource.master.password=123456
spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.dynamic.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
#druid连接池配置
spring.datasource.dynamic.datasource.master.druid.initial-size=5
spring.datasource.dynamic.datasource.master.druid.max-active=20
spring.datasource.dynamic.datasource.master.druid.min-idle=5
spring.datasource.dynamic.datasource.master.druid.max-wait=60000#test2从数据源配置
spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://127.0.0.1:3306/test2?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
spring.datasource.dynamic.datasource.slave.username=root
spring.datasource.dynamic.datasource.slave.password=123456
spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.dynamic.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource
#druid连接池配置
spring.datasource.dynamic.datasource.slave.druid.initial-size=5
spring.datasource.dynamic.datasource.slave.druid.max-active=20
spring.datasource.dynamic.datasource.slave.druid.min-idle=5
spring.datasource.dynamic.datasource.slave.druid.max-wait=60000#mybatis配置
mybatis.mapper-locations=classpath:org/example/mapper/*.xml
mybatis.configuration.cache-enabled=true
#开启驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true
#打印SQL
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

启动类

需要排除掉 DruidDataSourceAutoConfigure 类,不然启动会报错找不到配置的 url

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@Slf4j
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);log.info("------springboot running-----");}
}

实体类

@Data
@ApiModel
public class Goods implements Serializable {@ApiModelProperty(value = "商品id")private Long goodsid;@ApiModelProperty(value = "商品名称")@NotBlank(message = "商品名称不能为空")private String goodsname;@ApiModelProperty(value = "商品描述")@NotBlank(message = "商品描述不能为空")private String subject;@ApiModelProperty(value = "商品价格")@NotNull(message = "商品价格不能为空")private BigDecimal price;@ApiModelProperty(value = "商品库存", example = "0")@NotNull(message = "商品库存不能为空")private Integer stock;
}

service

至于 dao 层,使用的是 mybatis-generator 插件自动生成

@Service
public class GoodServiceImpl implements GoodService {@Autowiredprivate GoodsMapper goodsMapper;@Overridepublic Goods selectOneGoods(Long goodsid) {return goodsMapper.selectByPrimaryKey(goodsid);}@Overridepublic int addGoods(Goods goods) {return goodsMapper.insertSelective(goods);}
}

controller

@Controller
@RequestMapping(path = "/goods")
@Api(tags = "商品管理相关接口")
@Slf4j
public class GoodsController {@Autowiredprivate GoodService goodService;@GetMapping(path = "/selectOne")@ResponseBody@ApiOperation(value = "查询商品接口")@ApiImplicitParam(name = "id", value = "商品id", required = true)public ResultMap selectOne(@RequestParam(name = "id", defaultValue = "3") Long goodsid) {Goods goods = goodService.selectOneGoods(goodsid);log.info("查询到的商品数据:" + goods.toString());if (StringUtils.isEmpty(goods)) {return new ResultMap().fail().message("查询失败,没有您要的数据");}return new ResultMap().success().message("查询成功").data(goods);}@PostMapping(path = "/addGoods")@ResponseBody@ApiOperation(value = "添加商品的接口")public ResultMap addGoods(@Valid Goods goods, @NotNull BindingResult bindingResult) {if (bindingResult.hasErrors()){String defaultMessage = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();return new ResultMap().fail().message(defaultMessage);}int i = goodService.addGoods(goods);if (i > 0) {return new ResultMap().success().message("添加成功");}return new ResultMap().fail().message("添加失败");}
}

测试

service 层方法上都没有注解 @DS

使用 postman 测试第一个接口


使用 postman 测试第二个接口



以上两个接口测试说明:它们都默认操作的是主数据源 test1,证明我们配置文件中配置的主数据源 test1 是配置正确的,已经生效

service 层方法上加上注解 @DS 再测试

@Service
public class GoodServiceImpl implements GoodService {@Autowiredprivate GoodsMapper goodsMapper;@DS(value = "slave")// 切换数据源,并指定要访问的数据库名称@Overridepublic Goods selectOneGoods(Long goodsid) {return goodsMapper.selectByPrimaryKey(goodsid);}@Overridepublic int addGoods(Goods goods) {return goodsMapper.insertSelective(goods);}
}

使用 postman 测试第一个接口


此时 @DS 注解已生效,发生了数据源的动态切换

使用 postman 测试第二个接口



由于该接口没有 @DS 注解,所以没有发生数据源的切换,依然操作的是 test1 默认数据源

@DS 注解说明

注解 结果
没有@DS 默认数据源
@DS("dsName") dsName可以为组名也可以为具体某个库的名称
  • @DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解
  • @DS 官方建议使用在 service 层的方法上

该框架更详细的分析:https://blog.csdn.net/w57685321/article/details/106823660/
项目源码:https://gitee.com/chaojiangcj/springboot-dynamic-datasource

springboot实现数据库读写分离的一款框架相关推荐

  1. 跟我学Springboot开发后端管理系统5:数据库读写分离

    在Matrix-web后台管理系统中,使用到了数据库的读写分离技术.采用的开源的Sharding-JDBC作为数据库读写分离的框架.Matrix-Web后台数据库这一块采用的技术栈如下: 使用Myba ...

  2. 简单好用!利用Spring AOP技术10分钟实现一个数据库读写分离方案

    前言 最近我们的APP在线用户越来越多,接口的响应速度也是越来越慢,经过运维排查发现是由于并发查询太多导致的数据库压力比较大,架构师经过调研给出了数据库读写分离的解决方案,为了快速解决问题,我们最终采 ...

  3. mysql数据库字段变形_详解如何利用amoeba(变形虫)实现mysql数据库读写分离

    摘要:这篇MySQL栏目下的"详解如何利用amoeba(变形虫)实现mysql数据库读写分离",介绍的技术点是"MySQL数据库.数据库读写分离.amoeba.MySQL ...

  4. MySQL的主从配置+SpringBoot的MySQL读写分离配置

    MySQL的主从复制 点击前往查看MySQL的安装 1.主库操作 vim /etc/my.cnf 添加如下配置 log-bin=mysql-bin #[必须]启用二进制日志 server-id=128 ...

  5. jedis 读写分离_Redis实现数据库读写分离

    Redis是一种NoSQL的文档数据库,通过key-value的结构存储在内存中,Redis读的速度是110000次/s,写的速度是81000次/s,性能很高,使用范围也很广. 下面用一个实例实现re ...

  6. 解决数据库读写分离(转)

    如何配置mysql数据库的主从? 单机配置mysql主从:http://my.oschina.net/god/blog/496 常见的解决数据库读写分离有两种方案 1.应用层 http://neore ...

  7. 学会数据库读写分离、分表分库

    https://www.cnblogs.com/joylee/p/7513038.html 系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优 ...

  8. .net core发布 正在发现数据上下文_使用EF Core实现数据库读写分离

    以下文章来源于朝夕Net社区 ,作者Eleven 朝夕Net社区 朝气.丰富.活跃的.Net社区,朝夕教育携百万粉丝共同打造!有技术,有感悟,有新闻,有照片,有故事,还有梦想! [精选转载]| 作者/ ...

  9. PG SQL数据库读写分离的思路

    PGSQL可以设置一台主多个SLAVE,这样我们需要一个办法能在程序里做到读写分离,查询了互联网,找到了下面的解决思路,请周枫在后继开发中测试下面的思路方案: 在应用层通过spring特性解决数据库读 ...

  10. java spring mysql配置_java相关:mysql+spring+mybatis实现数据库读写分离的代码配置

    java相关:mysql+spring+mybatis实现数据库读写分离的代码配置 发布于 2020-4-4| 复制链接 分享一篇关于关于mysql+spring+mybatis实现数据库读写分离的代 ...

最新文章

  1. java的移植性_详细介绍JAVA的可移植性
  2. 频频霸榜的Python,竟遭开发者嫌弃!
  3. 计算机顶会论文投稿指南
  4. 概率论与数理统计中的算子半群 第一讲 Banach-Steinhaus定理1 Baire‘s Category与Banach-Steinhaus定理的证明
  5. VTK:柏拉图式固体用法实战
  6. LOL手游锤石上线吓坏玩家?英雄设计被吐槽,玩家:还我端游锤石
  7. Unity 白猫操作小实例
  8. esp32-智能语音-录音(保存于SD卡)
  9. 设计模式(十一):从文Finder中认识组合模式(Composite Pattern)
  10. Nature子刊:是穷是富与基因有关?大数据分析发现149个与收入相关基因位点
  11. javabean_企业JavaBean,基础架构预测以及更多行业趋势
  12. c语言 intptr_t
  13. 拼多多进军社区团购 店宝宝:巨头竞争加剧
  14. windows server 2008 进行多域名指向同一个ip
  15. console口 - 配置口
  16. 数据模型及E-R模型
  17. RTC与WebRTC有什么区别?
  18. mds聚类matlab,机器学习C9笔记:MDS聚类可视化
  19. 被吹上天的802.11ac Wave2到底好在哪?还有,Wave1哪去了?
  20. 编写一个方法,将一段文本中的各个单词的字母顺序翻转题

热门文章

  1. 翻译:使用 AWS Deep Racer 的日志分析工具
  2. 极客大学架构师训练营 系统架构 一致性哈希 Consistent Hashing 第五次作业
  3. 2021-09-08173. 二叉搜索树迭代器 栈
  4. 235.二叉搜索树的最近公共祖先
  5. 第二章随机过程的基本知识part I
  6. SSH免密码登录,搭建Flink standalone集群
  7. html =拼接dom,在js代码拼接dom对象到页面上去的模板总结(必看)
  8. 实验板FPGA型号在哪里看_【VE】一文看懂乙烯基树脂发展史!
  9. Torch环境搭建遇到的问题
  10. 编译原理完整学习笔记(四):语法分析