时间:2023-02-12 10:53:41 | 栏目:JAVA代码 | 点击:次
前篇博客介绍了用基本的方式做多数据源,可以应对一般的情况,但是遇到一些复杂的情况就需要扩展下功能了,比如:动态增减数据源、数据源分组,纯粹多库,读写分离一主多从,从其他数据库或者配置中心读取数据源等等。其实就算没有这些需求,使用此款框架实现多数据源也比之前要便捷,快速的多
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
版本: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>
配置文件详情可以参考官方文档
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; }
至于 dao
层,使用的是 mybatis-generator
插件自动生成
@Service public class GoodServiceImpl implements GoodService { @Autowired private GoodsMapper goodsMapper; @Override public Goods selectOneGoods(Long goodsid) { return goodsMapper.selectByPrimaryKey(goodsid); } @Override public int addGoods(Goods goods) { return goodsMapper.insertSelective(goods); } }
@Controller @RequestMapping(path = "/goods") @Api(tags = "商品管理相关接口") @Slf4j public class GoodsController { @Autowired private 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 { @Autowired private GoodsMapper goodsMapper; @DS(value = "slave")// 切换数据源,并指定要访问的数据库名称 @Override public Goods selectOneGoods(Long goodsid) { return goodsMapper.selectByPrimaryKey(goodsid); } @Override public int addGoods(Goods goods) { return goodsMapper.insertSelective(goods); } }
使用 postman
测试第一个接口
此时 @DS
注解已生效,发生了数据源的动态切换
使用 postman
测试第二个接口
由于该接口没有 @DS
注解,所以没有发生数据源的切换,依然操作的是 test1
默认数据源
@DS
注解说明
注解 | 结果 |
---|---|
没有@DS | 默认数据源 |
@DS("dsName") | dsName可以为组名也可以为具体某个库的名称 |
该框架更详细的分析:https://www.jb51.net/article/222550.htm
项目源码:https://gitee.com/chaojiangcj/springboot-dynamic-datasource