java每日一记 —— mybatis的动态数据源切换

动态数据源切换

  • 1.环境初始化
  • 2.切换数据源代码
  • 3.第二节代码的测试
  • 4.用注解的方式进行优化

此代码在jdk11上测试通过,SpringBoot版本为2.7.14

1.环境初始化

1.创建两个库

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- 表结构
DROP TABLE IF EXISTS `t_stu`;
CREATE TABLE `t_stu`  (`id` int NOT NULL COMMENT 'id',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`age` int NULL DEFAULT NULL,`sex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`class_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程名',`teacher` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '老师',`score` decimal(10, 2) NULL DEFAULT NULL COMMENT '分数',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;-- 库1数据
INSERT INTO `t_stu` VALUES (1, 'andy', 10, '男', '语文', '虚竹', 100.00);
-- 库2数据
INSERT INTO `t_stu` VALUES (1, 'lily', 10, '女', '数学', '小龙女', 100.00);

2.pom.xml

 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.14</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-rest</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.16</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies>

3.application.yml

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:db1:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/andy_test_1?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=falseusername: rootpassword: rootdb2:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/andy_test_2?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=falseusername: rootpassword: root

4.pojo类

public class Stu implements Serializable {private Integer id;private String name;private Integer age;private String className;private BigDecimal score;// getter...// setter...
}

5.mapper

@Mapper
public interface StuMapper  extends BaseMapper<Stu> {List<Stu> findAll();int insertStu(@Param("stu") Stu stu);}

6.mapper.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.andy.mapper.StuMapper"><select id="findAll" resultType="com.andy.pojo.Stu">select * from t_stu</select><insert id="insertStu" parameterType="com.andy.pojo.Stu">insert into t_stu(id,name)values(#{stu.id},#{stu.name})</insert>
</mapper>

7.controller

@RestController
public class TestController {@Resourceprivate StuMapper stuMapper;@GetMapping("/getData/{datasourceName}")public String getMasterData(@PathVariable("datasourceName") String datasourceName){DataSourceAndyContextHolder.setDataSource(datasourceName);List<Stu> all = stuMapper.findAll();DataSourceAndyContextHolder.removeDataSource();return all.get(0).getName();}@GetMapping("/insertData/{datasourceName}")@Transactional  // spring的事务注解,在本案例中不会生效public void insertData(@PathVariable("datasourceName") String datasourceName, @RequestBody Stu stu){DataSourceAndyContextHolder.setDataSource(datasourceName);stuMapper.insertStu(stu);// int i = 3/0; 这一行是为了测试事务,各位大佬可以自行测似DataSourceAndyContextHolder.removeDataSource();}
}

2.切换数据源代码

1.先来个存储数据源的map

public class DataSourceAndyContextHolder {// 此类提供线程局部变量。这些变量不同于它们的正常对应关系是每个线程访问一个线程(通过get、set方法),有自己的独立初始化变量的副本。private static final ThreadLocal<String> DATASOURCE_HOLDER = new ThreadLocal<>();/*** 设置数据源* @param dataSourceName 数据源名称*/public static void setDataSource(String dataSourceName){DATASOURCE_HOLDER.set(dataSourceName);}/*** 获取当前线程的数据源* @return 数据源名称*/public static String getDataSource(){return DATASOURCE_HOLDER.get();}/*** 删除当前数据源*/public static void removeDataSource(){DATASOURCE_HOLDER.remove();}}

2.实现动态切换数据源

public class DynamicDataAndySource extends AbstractRoutingDataSource {public DynamicDataAndySource(DataSource defaultDataSource, Map<Object, Object> targetDataSources){super.setDefaultTargetDataSource(defaultDataSource);super.setTargetDataSources(targetDataSources);}@Overrideprotected Object determineCurrentLookupKey() {return DataSourceAndyContextHolder.getDataSource();}
}

3.设置数据源

@Configuration
public class DateSourceAndyConfig {@Bean@ConfigurationProperties("spring.datasource.druid.db1")public DataSource masterDataSource(){return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties("spring.datasource.druid.db2")public DataSource slaveDataSource(){return DruidDataSourceBuilder.create().build();}@Bean(name = "dynamicDataSource")@Primarypublic DynamicDataAndySource createDynamicDataSource(){Map<Object,Object> dataSourceMap = new HashMap<>();DataSource defaultDataSource = masterDataSource();dataSourceMap.put("db1",defaultDataSource);dataSourceMap.put("db2",slaveDataSource());return new DynamicDataAndySource(defaultDataSource,dataSourceMap);}
}

3.第二节代码的测试

1.测试db1库

127.0.0.1:8080/getData/db1

在这里插入图片描述

2.测试db2库

127.0.0.1:8080/getData/db2

在这里插入图片描述

4.用注解的方式进行优化

1.导入坐标

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.定义一个注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface AndyDS {String value() default "db1";
}

3.定义切面

@Aspect
@Component
@Slf4j
public class DSAspect {@Pointcut("@annotation(com.andy.config.AndyDS)")public void dynamicDataSource(){}@Around("dynamicDataSource()")public Object datasourceAround(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature)point.getSignature();Method method = signature.getMethod();AndyDS ds = method.getAnnotation(AndyDS.class);if (Objects.nonNull(ds)){DataSourceAndyContextHolder.setDataSource(ds.value());}try {return point.proceed();} finally {DataSourceAndyContextHolder.removeDataSource();}}
}

4.测试代码

    @GetMapping("/getData_2")@AndyDS("db2") public List<Stu> getData_1(){List<Stu> all = stuMapper.findAll();return all;}

5.测试结果

127.0.0.1:8080/getData_2

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/256491.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

展望2024年供应链安全

2023年是开展供应链安全&#xff0c;尤其是开源治理如火如荼的一年&#xff0c;开源治理是供应链安全最重要的一个方面&#xff0c;所以我们从开源治理谈起。我们先回顾一下2023的开源治理情况。我们从信通院《2023年中国企业开源治理全景观察》发布的信息。信通院调研了来自七…

P8 Linux 目录操作

目录 前言 01 mkdir 系统调用 mkdir的代码示例 02 rmdir删除目录 03 打开、读取以及关闭目录 3.1 opendir()函数原型&#xff1a; 04 读取目录 readdir() 05 struct dirent 结构体&#xff1a; 06 rewinddir ()函数重置目录流 07 关闭目录 closedir ()函数 测试:打印…

fijkplayer flutter 直播流播放

fijkplayer flutter 直播流播放 fijkplayer 是 ijkplayer 的 Flutter 封装&#xff0c; 是一款支持 android 和 iOS 的 Flutter 媒体播放器插件&#xff0c; 由 ijkplayer 底层驱动。 通过纹理&#xff08;Texture&#xff09;接入播放器视频渲染到 Flutter 中。 前言 目前使用…

图灵测试:人工智能的终极挑战

图灵测试&#xff1a;人工智能的终极挑战 一、引言 在人工智能的发展历程中&#xff0c;图灵测试一直被视为一个重要的里程碑。这个由英国计算机科学家艾伦图灵提出的实验&#xff0c;旨在评估人工智能是否能够像人一样思考和表达&#xff0c;为人类与机器智能之间的界限设立了…

问题:antdv 在Modal中点击打开Modal,新的Modal显示在了前一个打开的Modal的下方

解决&#xff1a; 加上:zIndex"1001" <a-modalv-model:open"addUser_open"title"添加用户":zIndex"1001"> </a-modal>下面这是官网的描述&#xff0c;我们可以看到对话框组件默认的层级是1000&#xff0c;所以我们只要设…

实现跨VLAN通信、以及如何配路由协议

一、如下图片&#xff1a; 按照拓扑图所示&#xff0c;为LSW1,LSW2,AR1,AR2配置IP地址&#xff0c;线路左侧使用小地址&#xff0c;右侧用大地址&#xff0c;交换机中使用的管理VLAN编号是99。 两个路由器的配法&#xff1a; 注意&#xff1a;首先给每两个路由器之间要在相同的…

记录 | centos源码编译bazel

tensorflow的源码编译依赖于 bazel 这里进行 bazel 的源码编译 1、安装依赖 sudo yum install -y java-11-openjdk sudo yum install -y java-11-openjdk-devel sudo yum install -y protobuf-compiler zip unzip2、知悉要安装的 bazel 的版本 务必安装受支持的 Bazel 版本…

vcomp140.dll文件丢失解决方法分享:三种亲测有效方案

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“vcomp140.dll丢失”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;给使用者带来了很大的困扰。那么&#xff0c;vcomp140.dll丢失怎样修复呢&#xff1f;本文将详细介绍解决这…

听GPT 讲Rust源代码--src/tools(8)

File: rust/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs 在Rust源代码中&#xff0c;rust-analyzer是一个Rust编程语言的语言服务器。它提供了代码补全、代码重构和代码导航等功能来帮助开发者提高编码效率。 在rust-analyzer的代码目…

利用reddit的api进行爬虫

1 介绍 Reddit是一个社交新闻聚合网站&#xff0c;用户可以发布、评价和讨论各种话题。Reddit的内容涵盖了广泛的主题&#xff0c;可以从中获取大量的文本数据进行情绪分析。 2 注册 2.1 注册reddit 你需要先注册一个reddit的账号。 2.2 注册api https://www.reddit.com/…

快速测试 3节点的redis sentinel集群宕机2个节点以后是否仍能正常使用

有同事问我&#xff0c;三个redis sentinel节点&#xff0c;宕机两个节点以后&#xff0c;是否还能够正常的通过redis sentinel正常访问redis的数据。我想了想&#xff0c;理论上是可以的&#xff0c;但是我没试过&#xff0c;今天有时间就测试了一下。搭建环境和测试代码的郭晨…

教你如何一键生成微信分享卡片

今天说一种非常快捷的方式&#xff0c;快捷到什么程度呢&#xff1f; 1.关注微信公众号“C1N短网址服务” 2.发送你想要的链接内容&#xff0c;即可得到一张微信卡片 使用步骤&#xff1a; 按如下格式发送消息到公众号&#xff0c;公众号自动回复微信卡片&#xff0c;然后就…