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

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

spring:
  application:
    name: xxxx
  main:
    banner-mode: 'OFF'
  datasource:                 # 默认数据源 datamark
    druid:                    # 关闭数据库的 web 访问
      stat-view-servlet:
        enabled: false
      web-stat-filter:
        enabled: false
      filter:
        stat:
          enabled: false
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: ${spring.twodb.driver-class-name}
    url: ${spring.infodata.url}
    username: ${spring.xxx.username}
    password: ${spring.xxx.password}
    max-active: 100
    min-idle: 10
    initial-size: 10
    max-wait: 10000
    connection-error-retry-attempts: 5       # 设置重连次数
    break-after-acquire-failure: true        # 连接错误后退出
    time-between-connect-error-millis: 1000  # 重连间隔
  twodb:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: oracle.jdbc.OracleDriver
    url: jdbc:oracle:thin:@10.1.1.1:1528/sec
    username: xx
    password: xx
    max-active: 100
    min-idle: 10
    initial-size: 10
    max-wait: 10000
    connection-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
    @Primary
    public 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 {

    @Override
    protected 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;
    }

    @Override
    public 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);
    }
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

巴比达内网穿透:深度剖析其在解决远程连接挑战中的技术优势

在信息技术日新月异的今天&#xff0c;远程协作与管理的需求日益增长&#xff0c;但内网环境的隔离性一直是横亘在高效远程操作面前的一道坎。本文将深入探讨一款专为打破此壁垒而生的工具——巴比达内网穿透&#xff0c;如何以其技术创新和高效性能&#xff0c;成为解决远程连…

electron-builder 打包过慢解决

报错内容如下 > 6-241.0.0 build > electron-builder • electron-builder version24.13.3 os10.0.22631 • loaded configuration filepackage.json ("build" field) • writing effective config filedist\builder-effective-config.yaml • pack…

【Linux详解】进程地址空间

目录 研究背景 验证地址空间 实验一&#xff1a;父子进程变量地址一致性 实验二&#xff1a;变量值修改后父子进程的差异 分析与结论 实验三&#xff1a;进程地址空间验证 理解进程地址空间 区域与页表 写时拷贝机制 进程地址空间的意义 文章手稿&#xff1a; xmind…

7月信用卡新规下:信用卡欠的钱不用还了?

说到信用卡&#xff0c;现在基本上人手一张&#xff0c;大家都有使用过。但你知道吗&#xff0c;使用信用卡不是这么简单容易的事&#xff0c;比如会对你的贷款有影响&#xff0c;透支不还逾期对生活的影响&#xff0c;信用卡新规对持卡人和银行那边的影响。 一、只要不逾期&am…

hamibot 学习

1.参考文档&#xff1a; https://blog.csdn.net/zxl0428/article/details/1285318731.参考官网 快速入手步骤&#xff1a;注册&#xff0c;安装客户端&#xff0c;添加设备&#xff0c;开发脚本&#xff0c;运行脚本 https://hamibot.com/guide1.安装客户端 2.添加设备 …

高通骁龙(Qualcomm Snapdragon)CDSP HVX HTP 芯片简介与开发入门

1. Hexagon DSP/HVX/HTP 硬件演进 说到高通骁龙芯片大家应该不会陌生&#xff0c;其作为最为广泛的移动处理器之一&#xff0c;几乎每一个品牌的智能手机都会使用高通骁龙的处理器。 高通提供了一系列骁龙芯片解决方案。根据性能强弱分为了5个产品系列&#xff1a;从最高端的…

【neo4j图数据库】入门实践篇

探索数据之间的奥秘&#xff1a;Neo4j图数据库引领新纪元 在数字化浪潮汹涌的今天&#xff0c;数据已成为企业最宝贵的资产之一。然而&#xff0c;随着数据量的爆炸性增长和数据关系的日益复杂&#xff0c;传统的关系型数据库在处理诸如社交网络、推荐系统、生物信息学等高度互…

OPCUA相关概念和KepServer OPCUA连接PLC

文章背景 项目中需要使用OPC UA 来读取PLC的点位。本文简单介绍了OPC UA和使用KepServer软件连接PLC并读点。OPC相关概念 OPC之前&#xff0c;软件开发需要写大量驱动程序去连接设备&#xff0c;设备上的一个硬件改变&#xff0c;应用程序都有可能需要重写&#xff0c;不同设备…

水经微图Web版1.9.0发布

水经微图&#xff08;简称“微图”&#xff09;新版已上线&#xff0c;在该版本中主要新增了对WGS84图源加载、火星坐标图源加载和大字体图源加载功能&#xff0c;以及多面要素的加载功能。 现在&#xff0c;为你分享一下本轮迭代的主要新增功能&#xff0c;以及部分功能的效果…

STL空间配置器

空间配置器&#xff08;allocator&#xff09;&#xff08;重点&#xff09; 背景需求&#xff1a;在底层默默的实现空间的分配 问题&#xff1a;空间的申请与对象的创建两者分开&#xff0c;因为不断创建的时候可能会频繁的申请空间扩容。 类似操作&#xff1a;reserve函数…

自动扫描范围在减少剂量多相CT肝脏成像中的应用:基于CNN和高斯模型| 文献速递-深度学习自动化疾病检查

Title 题目 Automatic scan range for dose-reduced multiphase CT imaging of theliver utilizing CNNs and Gaussian models 自动扫描范围在减少剂量多相CT肝脏成像中的应用&#xff1a;基于CNN和高斯模型 01 文献速递介绍 肝癌是全球癌症死亡的第四大原因&#xff0c;每…

告别推广迷茫,Xinstall渠道包助您精准统计应用商店数据!

在App推广的浩瀚征途中&#xff0c;每一位广告主和开发者都面临着同样的挑战&#xff1a;如何在众多应用商店中脱颖而出&#xff0c;实现高效推广与精准获客&#xff1f;今天&#xff0c;就让我们一同探索Xinstall应用商店渠道包的独特魅力&#xff0c;看看它是如何成为解决这一…

【产品经理】聊聊PLG策略

PLG 是一种以用户增长为导向的策略&#xff0c;如何理解这种策略&#xff1f;适合采用PLG模式的SaaS又有哪些&#xff1f; 一、企业软件采购方式的变迁 从用户的角度&#xff1a;企业软件采购从CIO主导&#xff0c;逐渐演化为经理或者员工可做出决策。 从供应商的角度&#x…

剪映 v5.5 Pro Vip解锁版:使用指南与注意事项

摘要&#xff1a;本文介绍了剪映Pro VIP解锁版的使用方法&#xff0c;包括安装、测试和使用VIP素材的步骤&#xff0c;以及如何避免误报和保持解锁状态的建议。 正文&#xff1a; 剪映Pro是一款广受欢迎的视频编辑软件&#xff0c;提供了丰富的视频编辑功能和大量高质量的素材…

自动化测试报告pytest-html样式美化

最近我将 pytest-html 样式优化了 一版 先看优化前&#xff1a; 优化后&#xff1a; 优化内容包括&#xff1a; 删除部分多余字段新增echart图表部分字体大小、行间距、颜色做了美化调整运行环境信息移至报告最后部分字段做了汉化处理&#xff08;没全部翻译是因为&#xf…

python学习-函数

函数 函数&#xff1a;是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能的代码段。 内置函数可重复使用 为什么要学习、使用函数呢&#xff1f; 为了得到一个针对特定需求、可供重复利用的代码段 提高程序的复用性&#xff0c;减少重复性代码&#xff0c;…

记一次阿里云服务器java应用无法响应且无法远程连接的问题排查

问题表现 java服务无响应&#xff0c;无法远程链接到服务器。 今天中午12点多&#xff0c;应用直接崩溃。后续进入到服务器&#xff0c;发现java进程都不在了&#xff0c; 排查过程 先安装atop工具 安装、配置并使用atop监控工具 等下次再出现时看相关时间点日志&#xff…

Docker在windows上使用vscode远程连接容器

目录 一、提前准备&#xff1a; 二、vscode连接docker容器 三、构建好的docker容器直接连接vscode 四、Windows下的可视化出linux的ui界面 在日常的开发中&#xff0c;不想windows和linux两个系统之间来回切换&#xff0c;笔者最近打算所有的环境均在一个系统上完成。为了交…

26K Star!LLM多智能体AutoGen教程3:我的外包弟弟写代码

读到这里想必已经入门AutoGen了&#xff0c;但怎么让它自动写代码自动调试啊&#xff0c;我也想要一个外包弟弟给我干活&#xff0c;我就喝杯茶摸摸鱼审核一下代码就好了呀。这不巧了&#xff0c;最近PM要求我给他弄一份某SDK支持车厂的列表&#xff0c;这种简单的事情在以前我…

msvcp140_ATOMIC_WAIT.dll丢失的多种解决方法分享,实测有效

在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“msvcp140_ATOMIC_WAIT.dll丢失”。那么&#xff0c;msvcp140_ATOMIC_WAIT.dll丢失是怎么回事呢&#xff1f;本文将从msvcp140_ATOMIC_WAIT.dll丢失的原因分析、对电脑的影响以及解决方…