自定义动态数据源+事务控制

1:首先yml配置两个数据库的链接

spring:application:name: xxxxmain:banner-mode: 'OFF'datasource:                 # 默认数据源 datamarkdruid:                    # 关闭数据库的 web 访问stat-view-servlet:enabled: falseweb-stat-filter:enabled: falsefilter:stat:enabled: falsetype: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: ${spring.twodb.driver-class-name}url: ${spring.infodata.url}username: ${spring.xxx.username}password: ${spring.xxx.password}max-active: 100min-idle: 10initial-size: 10max-wait: 10000connection-error-retry-attempts: 5       # 设置重连次数break-after-acquire-failure: true        # 连接错误后退出time-between-connect-error-millis: 1000  # 重连间隔twodb:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: oracle.jdbc.OracleDriverurl: jdbc:oracle:thin:@10.1.1.1:1528/secusername: xxpassword: xxmax-active: 100min-idle: 10initial-size: 10max-wait: 10000connection-error-retry-attempts: 5       # 设置重连次数break-after-acquire-failure: true        # 连接错误后退出time-between-connect-error-millis: 1000  # 重连间隔

2:定义枚举

@AllArgsConstructor
@Getter
public enum DataSourceEnum {DEFAULT("default"), TWODB("twodb");private final String value;
}

2.1:方便后续需要用到数据源直接使用注解的形式进行切换即可
定义DataSource注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {DataSourceEnum source() default DataSourceEnum.DEFAULT;
}

3:项目启动配置数据库的链接信息

@Configuration
public class DataSourceConfig {@Bean(name = "default")@ConfigurationProperties(prefix = "spring.datasource")public DataSource defaultDataSource() {return DruidDataSourceBuilder.create().build();}@Bean(name = "twodb")@ConfigurationProperties(prefix = "spring.infodata")public DataSource infoDataSource() {return DruidDataSourceBuilder.create().build();}/*** 动态数据源配置*/@Bean@Primarypublic DataSource multipleDataSource(@Qualifier("default") DataSource defaultDataSource,@Autowired(required = false) @Qualifier("infodata") DataSource infodata) {MultipleDataSource multipleDataSource = new MultipleDataSource();Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(DataSourceEnum.DEFAULT.getValue(), defaultDataSource);if (defaultDataSource != null) {targetDataSources.put(DataSourceEnum.INFODATA.getValue(), infodata);}//添加数据源multipleDataSource.setTargetDataSources(targetDataSources);//设置默认数据源multipleDataSource.setDefaultTargetDataSource(defaultDataSource);return multipleDataSource;}}

4:管理动态数据源

public class MultipleDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSource();}
}

5:动态数据源上下文处理

public class DataSourceContextHolder {private static final ThreadLocal<String> contextHolder = new InheritableThreadLocal<>();/*** 设置数据源** @param db*/public static void setDataSource(String db) {contextHolder.set(db);}/*** 取得当前数据源** @return*/public static String getDataSource() {return contextHolder.get();}/*** 清除上下文数据*/public static void clear() {contextHolder.remove();}
}

6:使用aop动态代理实现数据源的切换

@Slf4j
@Aspect
@Component
public class DataSourceAspect implements Ordered {public static final String DEFAULT_SOURCE = DataSourceEnum.DEFAULT.getValue();public DataSourceAspect() {}@Pointcut("@within(DataSource注解所在额包路径) || @annotation(DataSource注解所在额包路径))")public void dataSourcePointCut() {}@Around("dataSourcePointCut()")public Object around(ProceedingJoinPoint point) {String source = DataSourceContextHolder.getDataSource();MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();Class<?> aClass = point.getTarget().getClass();DataSource annotation = aClass.getAnnotation(DataSource.class);DataSource dataSource = method.getAnnotation(DataSource.class);if (needSwitchDataSource(point)) {if (annotation != null) {DataSourceContextHolder.setDataSource(annotation.source().getValue());log.debug("set datasource is " + annotation.source().getValue());} else {DataSourceContextHolder.setDataSource(dataSource.source().getValue());log.debug("set datasource is " + dataSource.source().getValue());}}Object var5;try {var5 = point.proceed();} catch (Throwable e) {throw new CustomException(e.getMessage(), e);} finally {if (needSwitchDataSource(point)) {DataSourceContextHolder.setDataSource(source);log.debug("clean datasource");}}return var5;}private boolean needSwitchDataSource(ProceedingJoinPoint point) {MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();Class<?> aClass = point.getTarget().getClass();DataSource annotation = aClass.getAnnotation(DataSource.class);DataSource dataSource = method.getAnnotation(DataSource.class);return annotation != null || dataSource != null;}@Overridepublic int getOrder() {return 1;}
}

7:在切换数据源直接查询时候需要将事务进行重新创建一个新事物处理事务的情况 如下使用
在业务类型上添加如下的代码实现切换

@Slf4j
@Service
@DataSource(source = DataSourceEnum.TWODB)
public class xxx{@Override@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)public List<SecuryInfo> getSecuryInfoBySecuID(List<String> secuIdList) {return  poolVarSecuInfoDao.selectSecuInfoByCond(null,null,secuIdList);}
}

以上是自定义动态数据源+事务控制 关注老哥带你上高速 。。。。。。。。。
在这里插入图片描述

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

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

相关文章

Linux系统之玩转SafeLine防火墙应用

Linux系统之玩转SafeLine防火墙应用 一、SafeLine介绍1.1SafeLine简介1.2 SafeLine功能1.3 SafeLine 的工作原理二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、部署SafeLine4.1 安…

一篇文章搞懂弹性云服务器和轻量云服务器的区别

前言 在众多的云服务器类型中&#xff0c;弹性云服务器和轻量云服务器因其各自的特点和优势&#xff0c;受到了广大用户的青睐。那么&#xff0c;这两者之间到底有哪些区别呢&#xff1f;本文将为您详细解析。 弹性云服务器&#xff1a;灵活多变的计算资源池 弹性云服务器&…

谷粒商城-个人笔记(集群部署篇一)

前言 ​学习视频&#xff1a;​Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强​学习文档&#xff1a; 谷粒商城-个人笔记(基础篇一)谷粒商城-个人笔记(基础篇二)谷粒商城-个人笔记(基础篇三)谷粒商城-个人笔记(高级篇一)谷粒商城-个…

【LeetCode的使用方法】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 🔮LeetCode的使用方法 🔮LeetCode 是一个在线编程平台,广泛…

《昇思25天学习打卡营第7天|函数式自动微分》

文章目录 今日所学&#xff1a;一、函数与计算图二、微分函数与梯度计算三、Stop Gradient四、Auxiliary data五、神经网络梯度计算总结 今日所学&#xff1a; 今天我学习了神经网络训练的核心原理&#xff0c;主要是反向传播算法。这个过程包括将模型预测值&#xff08;logit…

无法定位程序输入点Z9 qt assertPKcS0i于动态链接库F:\code\projects\06_algorithm\main.exe

解决方法&#xff1a; 这个报错&#xff0c;是因为程序在运行时没要找到所需的dll库&#xff0c;如果把这个程序方法中对应库的目录下执行&#xff0c;则可正常执行。即使将图中mingw_64\bin 环境变量上移到msvc2022_64\bin 之前也不可以。 最终的解决方法是在makefile中设置环…

Python基础小知识问答系列-可迭代型变量赋值

1. 问题&#xff1a; 怎样简洁的把列表中的元素赋值给单个变量&#xff1f; 当需要列表中指定几个值时&#xff0c;剩余的变量都收集在一起&#xff0c;该怎么进行变量赋值&#xff1f; 当只需要列表中指定某几个值&#xff0c;其他值都忽略时&#xff0c;该怎么…

使用Redis实现消息队列:List、Pub/Sub和Stream的实践

摘要 Redis是一个高性能的键值存储系统&#xff0c;它的多种数据结构使其成为实现消息队列的理想选择。本文将探讨如何使用Redis的List、Pub/Sub和Stream数据结构来实现一个高效的消息队列系统。 1. 消息队列的基本概念 消息队列是一种应用程序之间进行通信的机制&#xff0…

660错题

不能局部求导,局部洛必达

Swift 中强大的 Key Paths(键路径)机制趣谈(上)

概览 小伙伴们可能不知道&#xff1a;在 Swift 语言中隐藏着大量看似“其貌不扬”实则却让秃头码农们“高世骇俗”&#xff0c;堪称卧虎藏龙的各种秘技。 其中&#xff0c;有一枚“不起眼”的小家伙称之为键路径&#xff08;Key Paths&#xff09;。如若将其善加利用&#xff…

pjsip环境搭建、编译源码生成.lib库

使用平台&#xff1a; windows qt(5.15.2) vs(2019)x86 pjsip版本以及第三方库使用 pjsip 2.10 ffmpeg4.2.1 sdl2.0.12pjsip源码链接&#xff1a; https://github.com/pjsip/pjproject源码环境配置 首先创建两个文件夹&#xff0c;分别是include、lib其中include放置ff…

p2p、分布式,区块链笔记: 通过libp2p的Kademlia网络协议实现kv-store

Kademlia 网络协议 Kademlia 是一种分布式哈希表协议和算法&#xff0c;用于构建去中心化的对等网络&#xff0c;核心思想是通过分布式的网络结构来实现高效的数据查找和存储。在这个学习项目里&#xff0c;Kademlia 作为 libp2p 中的 NetworkBehaviour的组成。 以下这些函数或…

Android 输入系统 InputStage

整体流程如上所说&#xff0c;简要归纳如下&#xff1a; 输入法之前的处理 输入法处理 输入法之后处理 综合处理 InputStage将输入事件的处理分成若干个阶段&#xff08;Stage&#xff09;, 如果当前有输入法窗口&#xff0c;则事件处理从 NativePreIme 开始&#xff0c;否…

主流国产服务器操作系统技术分析

主流国产服务器操作系统 信创 "信创"&#xff0c;即信息技术应用创新&#xff0c;作为科技自立自强的核心词汇&#xff0c;在我国信息化建设的进程中扮演着至关重要的角色。自2016年起步&#xff0c;2020年开始蓬勃兴起&#xff0c;信创的浪潮正席卷整个信息与通信技…

GNeRF代码复现

https://github.com/quan-meng/gnerf 之前一直去复现这个代码总是文件不存在&#xff0c;我就懒得搞了&#xff08;实际上是没能力哈哈哈&#xff09; 最近突然想到这篇论文重新试试复现 一、按步骤创建虚拟环境安装各种依赖等 二、安装好之后下载数据&#xff0c;可以用Blen…

virtualbox+Ubuntu部分窗口显示错乱

如下图&#xff1a; 窗口标题显示错乱&#xff0c;跟一般乱码不一样。 解决办法&#xff1a; 在virtualbox设置中&#xff0c;显示选项卡&#xff0c;取消勾选启用3D加速 也可参考此链接&#xff1a;linux ubuntu 中vscode中央窗口显示出现异常/显示错误_开发工具-CSDN问答

打卡第一天

今天是参加算法训练营的第一天&#xff0c;希望我能把这个训练营坚持下来&#xff0c;希望我的算法编程题的能力有所提升&#xff0c;不再面试挂了&#xff0c;面试总是挂编程题&#xff0c;记录我leetcode刷题数量&#xff1a; 希望我通过这个训练营能够实现两份工作的无缝衔接…

自动化任务工具 -- zTasker v1.94 绿色版

软件简介 zTasker 是一款功能强大的自动化任务管理软件&#xff0c;以其简洁易用、一键式操作而著称。软件体积小巧&#xff0c;启动迅速&#xff0c;提供了超过100种任务类型和30多种定时/条件执行方法&#xff0c;能够满足用户在自动化方面的多样化需求。 zTasker 支持定时任…

从全连接到卷积

一、全连接到卷积 1、卷积具有两个原则&#xff1a; 平移不变性&#xff1a;无论作用在哪个部分&#xff0c;它都要有相同的作用&#xff0c;而不会随着位置的改变而改变 局部性&#xff1a;卷积核作用处&#xff0c;作用域应该是核作用点的周围一小部分而不作用于更大的部分 …