新年新气象---多数据源配置

2023-11-16

概述:2022年第一天,在这祝大家新年快乐,好运连连,事业爱情双丰收。本文主要是通过注解结合aop的方式实现多数据源的动态切换。

一、配置文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      #主数据源
	  master:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://ip地址:3306/数据库名?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
        username: 用户名
        password: 密码
      #另一个数据源
      slave-one:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://ip地址:3306/数据库名?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
        username: 用户名
        password: 密码

连接池用的druid,上面配置根据自身更改。

二、去除springboot的数据源自动配置

//主启动类中
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

三、定义注解和切面

//注解
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String value() default (默认数据源名称)DataSourceName.MASTER;
}

//切面
@Aspect
@Component
public class DataSourceAspect implements Ordered {
    /**
     * 切点: 所有配置 DataSource 注解的方法
     */
    @Pointcut("@annotation(注解类全限定名)")
    public void dataSourcePointCut() {}

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        DataSource ds = method.getAnnotation(DataSource.class);
        // 动态判断当前方法应用哪个数据源
        DynamicDataSource.setDataSource(ds.value());
        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }
    @Override
    public int getOrder() {
        return 1;
    }
}

四、配置数据源bean

//数据源bean
@Configuration
public class DataSourceConfig {

    @Bean(name = "masterDataSource")
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slaveOneDataSource")
    @ConfigurationProperties("spring.datasource.druid.slave-one")
    public DataSource slaveOneDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("slaveOneDataSource") DataSource slaveOneDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put(DataSourceName.MASTER, masterDataSource);
        targetDataSources.put(DataSourceName.SLAVE_ONE, slaveOneDataSource);
        // 还有数据源,在targetDataSources中继续添加
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }
}


//通过AbstractRoutingDataSource实现动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    /**
     * 配置DataSource, defaultTargetDataSource为主数据库
     */
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

    public static void clearDataSource() {
        contextHolder.remove();
    }
}

五、测试方法

//数据源名称,也可定义为枚举类
public interface DataSourceName {

    String MASTER = "MASTER";

    String SLAVE_ONE = "SLAVE_ONE";
}


//使用方式:service的impl加上注解@DataSource(数据源名称)即可
@DataSource(DataSourceName.SLAVE_ONE)
@Override
public Integer saveData(Object object) {
	return  xxxMapper.saveData(object);
}

注意:

  • 调用数据源切换方法的位置不能在同一个类中
  • 数据源切换必须在事务开启前

比如我之前遇到的问题:我在service层通过切面方式对update*、save*等更新方法加了事务,然后在其他service中调用了带数据源切换的方法,结果,切换失败了,因为在service中已经开启了事务,确定了数据源,再调用带切换数据源注解的方法已经不会生效了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

新年新气象---多数据源配置 的相关文章

  • 从txt文件中读取数据而不下载它?

    我想从提供的文本文件中解析信息 有没有一种方法可以在应用程序中执行此操作 而无需先下载文件 以某种方式传输文本内容 打开到 URL 的 Http 连接 使用内置 HttpURLConnection 或使用 commons httpclien
  • 将 WAR 部署到 Tomcat(Spring Boot + Angular)

    我正在尝试使用以下命令部署 Spring Boot 应用程序WAR包装至Tomcat 10 应用程序已成功部署 但是 当我尝试访问端点时 它会导致404 未找到 战争文件 应用程序 war http localhost 8080 appli
  • 使用itext java库复制时pdf文件大小大大增加

    我正在尝试使用 Java 中的 itextpdf 库将现有的 pdf 文件复制到一些新文件中 我使用的是 itextpdf 5 5 10 版本 我在两种方式上都面临着不同的问题 PDFStamper 和 PdfCopy 当我使用 PDFSt
  • Selector.close() 是否关闭所有客户端套接字?

    我是 nio 套接字的新手 我已经使用 nio 套接字编写了一个服务器 现在我正在尝试编写关闭钩子以确保通过清理资源正常退出 我的问题是Selector close 方法关闭所有客户端套接字 如果没有 请告诉我如何访问所有客户端套接字 而无
  • Java 错误和警告列表

    在哪里 如何获得所有 java 和 javac 的错误和警告消息的列表 This http mindprod com jgloss compileerrormessages html我认为页面是您所需要的
  • 二元运算符 >=、-、* 的错误操作数类型

    我无法弄清楚如何修复代码中不断出现的这些错误 import java util Scanner public class Unit02Prog1 public static void main String args Scanner inp
  • 无法在 Intellij 中运行主类[重复]

    这个问题在这里已经有答案了 我有以下项目结构 ProjectRoot src Main examples libs My src文件夹被标记为sources在 Intellij 中 现在 当我想运行 Main 类时 出现以下错误 Excep
  • 如何杀死 Java Future?

    我正在开发的服务使用 Future 来并行运行多个任务 每个任务最多可能需要一分钟才能完成 然而 外部库似乎有问题 因为在某些情况下 2 的时间 它不会返回 在这些情况下 我想给出 2 分钟的等待时间 如果还没有返回 我想杀死 future
  • java:为什么主线程等待子线程完成

    我有一个简单的java程序 主线程 main 创建并启动另一个线程t class T extends Thread Override public void run while true System out println Inside
  • 如何检查单词是否在wordNet中

    我开始了解wordNet直到我知道我找到了synonymous对于一个特定的词 现在我有一个文件 我想使用标记化该文本n gram例如 String s I like to wear tee shirt 使用后n gram这将是 I lik
  • 在 Eclipse 中删除空块之前的新行

    我更喜欢奥尔曼式 http en wikipedia org wiki Brace style Allman style大括号 例如 if foo magical prancing unicorn stuff 而不是 if foo unma
  • java彩色滚动条搜索结果

    我将如何在 Java 中自定义滚动条 以便我可以进行像 chrome 一样的搜索 也就是说在结果所在的位置放置彩色条纹 我不想要一个库 因为我更喜欢自己编写代码 另外 我不想失去我拥有的 L F 欢迎举例 实际上 它将查看一个大的文本文件或
  • 如何获取 JDBC 中 UPDATE 查询影响的所有行?

    我有一项任务需要使用更新记录PreparedStatement 一旦记录被更新 我们知道更新查询返回计数 即受影响的行数 但是 我想要的不是计数 而是受更新查询影响的行作为响应 或者至少是受影响的行的 id 值列表 这是我的更新查询 UPD
  • Java 8:如何创建毫秒、微秒或纳秒的 DateTimeFormatter?

    我需要创建格式化程序来解析具有可选的毫秒 微米或纳秒分数的时间戳 例如 对于我的需求 我看到以下机会 DateTimeFormatter formatter new DateTimeFormatterBuilder append DateT
  • 如果 Modelmapper 中的整个属性为空,如何排除它们

    ModelMapper 是否 http modelmapper org http modelmapper org 支持什么排除属性 如果该值为空 我刚刚找到了 PropertyMap 但这对我来说是一种限制 因为我必须描述我想要的特定属性
  • Spring 如何在运行时获取有关“强类型集合”的泛型类型信息?

    我在 Spring 3 0 文档中阅读了以下内容 强类型集合 仅限 Java 5 在 Java 5 及更高版本中 您可以使用强类型集合 使用泛型类型 也就是说 可以声明一个 Collection 类型 使其只能包含 String 元素 例如
  • 为什么/何时应该使用泛型方法?

    学习Java的时候遇到过通用方法 public
  • 使用 Hibernate Envers 的复合表

    我有一个带有复合表的应用程序 其中包含一个额外的列 一切正常 直到我们添加 Hibernate Envers Audited org hibernate MappingException 无法读取 no pack response Resp
  • junit4 使用特定测试方法创建测试套件

    在 junit4 中 我想执行来自不同类的特定测试方法 即想要使用来自不同类的特定测试方法创建一个测试套件 假设我有两门课 public class Test Login Test public void test Login 001 Sy
  • JPA ManyToMany 产生的空联接表

    我有一个应用程序 其中我尝试使用 Hibernate 作为 JPA 提供程序来实现两个实体之间的多对多关系 我正在尝试的例子是一个单向的 其中一个相机可以有多个镜头 而镜头可以安装到多个相机中 以下是我的实体类 只需粘贴其中的相关部分 Ca

随机推荐

  • 软件测试开发学习——第六天

    静态白盒测试 检查设计和代码 静态白盒测试 在不执行软件的条件下有条理地仔细审查软件设计 体系结构和代码 从而找出软件的缺陷的过程 有时称为结构化分析 进行白盒测试的首要原因是尽早发现软件缺陷 以找出动态黑盒测试难以发现或隔离的软件缺陷 白
  • elasticsearch7.17.3实现按terms传入内容排序,类似mysql中order by filed()的排序方式

    现有一个需求 需要在elasticsearch中实现用terms筛选内容 并且按terms传入的内容顺序排列 类型于mysql中order by filed 的排序方式 具体实现如下 目录 一 需求 二 整体思路 三 es查询语句 四 ja
  • (Hibernate学习篇)Web 项目搭建Hibernate框架

    第一步 Web项目搭建Hibnate框架 myeclipse集成hibernate框架 如图 第二 选择Hibernate版本 DB 驱动 myeclipse database Expler中创建 myeclipse 默认的版本是hiber
  • matlab中求特征值的eig函数说明

    matlab中求特征值的eig函数说明 1 基本用法 e eig A 返回一个列向量 其中包含方阵 A 的特征值 示例 V D eig A 返回特征值的对角矩阵 D 和矩阵 V 其列是对应的右特征向量 使得 AV VD 示例 V D W e
  • IPSEC VPN知识点总结

    具体的实验 使用IPSEC VPN实现隧道通信 使用IPSEC VPN在有防火墙和NAT地址转换的场景下实现隧道通信 DS VPN实验 目录 1 什么是数据认证 有什么作用 有哪些实现的技术手段 2 什么是身份认证 有什么作用 有哪些实现的
  • iOS 设置项目的version和build号

    设置项目的version和build号 Version 1 0 1 Build 1 0 1 1 Version是显示对外的版本号 itunesconect和Appstore用户可以看到 对应O C中获取version的值 NSBundle
  • Servlet 中 session 的创建、销毁及监听

    1 session 和 cookie 关于session和cookie详细的内在机制和区别 请另行查阅资料 可参看 Session机制详解 当客户端首次请求session对象时候 服务器会为其创建一个session 并计算出具有唯一性的se
  • Ceph—报错锦集(mgr2、pgs、mgr依赖缺失等)

    Ceph 手动部署Ceph报错锦集 mgr2 pgs mgr依赖缺失等 报错锦集 1 执行 do cmake sh时的报错提示 2 do cmake sh 的note 3 导入一些链接库 4 No module named ceph mgr
  • Android Studio编译报错:sdk:minSdkVersion 1 cannot be smaller than version 7 declared in library

    背景 有一个以前的项目从Eclipse迁移到Android Studio 结果编译的时候报错如下 Error Execution failed for task lDrawer processDebugAndroidTestManifest
  • ListView动态加载数据

    当listview需要加载的数据过多时 若一次性载入则速度会相当缓慢 影响用户体验 这时候就需要动态加载数据 即每次载入固定长度的数据 android market的listview就是采用这种方式 使得加载看起来很平滑 响应速度很快 有助
  • 物联网的四种计算类型

    简介 从一个实践者的角度来看 我经常看到计算更加可用和分布的必要性 当我开始将物联网与OT和IT系统集成时 我面临的第一个问题是设备发送到我们服务器的数据量太大 我在一个工厂自动化场景中工作 我们集成了400个传感器 这些传感器每1秒发送3
  • Qt内存管理(三) Qt的智能指针

    智能指针则可以在退出作用域时 不管是正常流程离开或是因异常离开 总调用delete来析构在堆上动态分配的对象 Qt常用的智能指针有QPointer QScopedPointer QSharedPointer 关于这几个智能指针 网上的博客基
  • 每天一个linux命令(30): chown命令

    chown将指定文件的拥有者改为指定的用户或组 用户可以是用户名或者用户ID 组可以是组名或者组ID 文件是以空格分开的要改变权限的文件列表 支持通配符 系统管理员经常使用chown命令 在将文件拷贝到另一个用户的名录下之后 让用户拥有使用
  • 双系统卸载Linux,重装Deepin

    卸载掉之前的Linux系统 参考资料 https www bilibili com video av209430195 下载diskgenius https www diskgenius cn download php 删除Linux分区
  • StackExchange.Redis Timeout performing 超时问题

    最近在做的一个项目 用的 net core 2 1 然后缓存用的Redis 缓存相关封装是同事写的 用的驱动是StackExchange Redis version 2 0 571 一直听说这个驱动并发情况下有TimeOut bug 项目开
  • Flutter--Button浅谈

    作为一个常用到不能再常用的组件 material库中的button组件都有一点奇怪 存在无法设置的内外边距 我们做一个简单的展示 选几个常见button 统一使用Text做child 外加一个带红色的Container组件 观察margin
  • JavaScript-1-100之间整数的和

    要求 求1 100之间整数的和 实现代码
  • 图像数据库

    ImageNet ImageNet是一个计算机视觉系统识别项目 是目前世界上图像识别最大的数据库 是美国斯坦福的计算机科学家李飞飞模拟人类的识别系统建立的 能够从图片识别物体 目前已经包含14197122张图像 是已知的最大的图像数据库 每
  • $(this).parent("tr").find("td").eq(0).text()

    this parent tr find td eq 0 text
  • 新年新气象---多数据源配置

    概述 2022年第一天 在这祝大家新年快乐 好运连连 事业爱情双丰收 本文主要是通过注解结合aop的方式实现多数据源的动态切换 一 配置文件 spring datasource type com alibaba druid pool Dru