详解Spring多数据源如何切换

 更新时间:2024年06月30日 11:21:17   作者:Bug生产猿  
这篇文章主要介绍了spring多数据源的如何切换,由于是spring项目,可以借助 spring 的DataSource 对象去管理,大体思路是创建一个类实现该接口,替换spring原有的DataSource 对象,文中有详细的代码示例供大家参考,需要的朋友可以参考下

由于是spring项目,可以借助 spring 的DataSource 对象去管理,大体思路是创建一个类(比如MyRoutingDataSource)实现该接口,替换spring原有的DataSource 对象,通过MyRoutingDataSource 管理需要spring真实的干活的数据源,这是属于哪种设计模式??

spring jdbc 已经考虑到了,继承spring中 AbstractRoutingDataSource 抽象类实现determineCurrentLookupKey 方法,setTargetDataSources方法用map形式传入所需要切换数据源,是模板方法设计模式??

在Spring框架中实现多数据源配置并切换通常涉及以下步骤:

1.定义数据源

在Spring配置文件中(XML或Java Config)定义多个DataSource bean。

 2.配置JPA或MyBatis

如果你使用JPA,你可能需要为每个数据源配置一个EntityManagerFactoryTransactionManager。如果你使用MyBatis,你可能需要为每个数据源配置一个SqlSessionFactorySqlSessionTemplate

3.使用@Qualifier 或 @Primary

当你有多个相同类型的bean时,你可以使用@Qualifier注解来指定要注入的bean。或者,你可以使用@Primary注解来标记一个数据源作为主要的,以便在不需要明确指定时自动注入。

4.实现数据源路由

数据源路由是实现多数据源切换的关键。你可以通过继承AbstractRoutingDataSource来创建自定义的数据源,该数据源可以根据当前线程或请求上下文中的某个标识符来切换数据源。

5.使用AOP或拦截器设置数据源

在请求处理之前,你可以使用AOP或拦截器来设置当前线程的数据源标识符。这样,当数据访问层(如JPA仓库或MyBatis Mapper)尝试获取数据源时,它将通过你的自定义数据源路由逻辑来获取正确的数据源。

示例代码

自定义数据源路由

public class DynamicDataSource extends AbstractRoutingDataSource {  
  
    @Override  
    protected Object determineCurrentLookupKey() {  
        // 这里可以根据需要返回不同的数据源标识符  
        // 例如,从ThreadLocal中获取当前线程的数据源标识符  
        return DataSourceContextHolder.getCurrentDataSource();  
    }  
}  
  
// 用于保存当前线程的数据源标识符的工具类  
public class DataSourceContextHolder {  
  
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();  
  
    public static void setCurrentDataSource(String dataSource) {  
        contextHolder.set(dataSource);  
    }  
  
    public static String getCurrentDataSource() {  
        return contextHolder.get();  
    }  
  
    public static void clearCurrentDataSource() {  
        contextHolder.remove();  
    }  
}

配置数据源

@Configuration  
public class DataSourceConfig {  
  
    @Bean(name = "primaryDataSource")  
    @ConfigurationProperties(prefix = "spring.datasource.primary")  
    public DataSource primaryDataSource() {  
        // ... 配置并返回DataSource 
        return DataSourceBuilder.create().build(); 
    }  
  
    @Bean(name = "secondaryDataSource")  
    @ConfigurationProperties(prefix = "spring.datasource.secondary")  
    public DataSource secondaryDataSource() {  
        // ... 配置并返回DataSource  
        return DataSourceBuilder.create().build();
    }  
  
    @Bean(name = "dataSource")  
    public DataSource dynamicDataSource() {  
        DynamicDataSource dataSource = new DynamicDataSource();  
        Map<Object, Object> targetDataSources = new HashMap<>();  
        targetDataSources.put("primary", primaryDataSource());  
        targetDataSources.put("secondary", secondaryDataSource());  
        dataSource.setTargetDataSources(targetDataSources);  
        dataSource.setDefaultTargetDataSource(primaryDataSource());  
        return dataSource;  
    }  
  
    // 配置其他必要的组件,如EntityManagerFactory和TransactionManager(如果需要)  
}

使用AOP或拦截器设置数据源

@Aspect  
@Component  
public class DataSourceAspect {  
  
    @Pointcut("@annotation(customDataSource)")  
    public void dataSourcePointcut(CustomDataSource customDataSource) {}  
  
    @Before("dataSourcePointcut(customDataSource)")  
    public void switchDataSource(JoinPoint joinPoint, CustomDataSource customDataSource) {  
        DataSourceContextHolder.setCurrentDataSource(customDataSource.value());  
    }  
  
    @After("@annotation(customDataSource)")  
    public void restoreDataSource(JoinPoint joinPoint, CustomDataSource customDataSource) {  
        DataSourceContextHolder.clearCurrentDataSource();  
    }  
}  
  
// 自定义注解,用于指定数据源  
@Target({ElementType.METHOD, ElementType.TYPE})  
@Retention(RetentionPolicy.RUNTIME)  
public @interface CustomDataSource {  
  
    String value() default "primary";  
}

现在,你可以在需要指定数据源的方法上使用@CustomDataSource注解来切换数据源。在方法执行之前,AOP切面将设置当前线程的数据源标识符,并在方法执行后清除它。这样,数据访问层就可以通过DynamicDataSource获取正确的数据源了。

到此这篇关于详解Spring多数据源如何切换的文章就介绍到这了,更多相关Spring多数据源切换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

    如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

    这篇文章主要介绍了如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • 教你在Spring Boot微服务中集成gRPC通讯的方法

    教你在Spring Boot微服务中集成gRPC通讯的方法

    这篇文章主要介绍了教你在Spring Boot微服务中集成gRPC通讯的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • logback自定义json日志输出示例详解

    logback自定义json日志输出示例详解

    这篇文章主要为大家介绍了logback自定义json日志输出,就是通过logback日志体系以及logstash提供的json log依赖将数据以json格式记录到日志文件的例子
    2022-03-03
  • Java编程删除链表中重复的节点问题解决思路及源码分享

    Java编程删除链表中重复的节点问题解决思路及源码分享

    这篇文章主要介绍了Java编程删除链表中重复的节点问题解决思路及源码分享,具有一定参考价值,这里分享给大家,供需要的朋友了解。
    2017-10-10
  • java和jsp中的request使用示例

    java和jsp中的request使用示例

    这篇文章主要介绍了java和jsp中的request使用示例,需要的朋友可以参考下
    2014-02-02
  • springboot连接不上redis的三种解决办法

    springboot连接不上redis的三种解决办法

    这篇文章主要介绍了springboot连接不上redis的三种解决办法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Ubuntu搭建Java开发环境笔记

    Ubuntu搭建Java开发环境笔记

    这篇文章主要介绍了Ubuntu搭建Java开发环境笔记,本文讲解了JDK安装、MyEclipse安装及第一个Hello world程序等内容,需要的朋友可以参考下
    2015-03-03
  • Java实现图片对比功能

    Java实现图片对比功能

    个人从来没有研究过图像学,也没看过什么论文或者相关文档,写这个完全是靠google和百度,自己写了个实验了下,测试用例也少,估计有大BUG的存在,所以看的人权当学习交流,切勿生产使用。
    2014-09-09
  • java 数据的加密与解密普遍实例代码

    java 数据的加密与解密普遍实例代码

    本篇文章介绍了一个关于密钥查询的jsp文件简单实例代码,需要的朋友可以参考下
    2017-04-04
  • Java连接MySQL数据库命令行程序过程

    Java连接MySQL数据库命令行程序过程

    SQL编程包括两种形式,一种是过程化编程,主要通过数据库交互式工具,通过存储过程、触发器、函数等形式的编程;另一种是嵌入式SQL编程,将SQL语句嵌入到高级开发语言,完成数据的各种操作
    2021-10-10

最新评论