浅析spring中的多数据源解决方案AbstractRoutingDataSource的使用

springboot之AbstractRoutingDataSource抽象类实现动态多数据源切换原理解析 之前写过两篇实现动态多数据源的文章: 第一种:半自动化模式https://blog.youkuaiyun.com/yaomingyang/article/details/100807675 第二种:完全自动化配置模式:https://blog.youkuaiyun.com/yaomingyang/article/details/117089979 但是一直未对其实现的核心抽象类AbstractRoutingDataSource进行讲解,今天我们就来看下这个抽象类的源码实现原理;先看下部分源码: /** * Abstract {@ 阅读详情

浅析spring中的多数据源解决方案AbstractRoutingDataSource的使用

AbstractRoutingDataSource是spring提供的一种多数据源解决方案,其继承关系如下图所示。

AbstractRoutingDataSource

上图中没有将一些属性展示出来,这里挑几个重点的属性简单分析一下。

private Map<Object, Object> targetDataSources;
private Object defaultTargetDataSource;
private boolean lenientFallback = true;
private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
private Map<Object, DataSource> resolvedDataSources;
private DataSource resolvedDefaultDataSource;

targetDataSources就是需要设置的多数据源,可理解为从数据源,对应的defaultTargetDataSource可理解为主数据源,这两个属性均可通过对应的setter进行设置。lenientFallback直接翻译有点怪怪的,简单理解,当通过路由查找键找不到对应的数据源时,是否使用默认的数据源,默认是true。至于后面两个resolvedXXX,其实对应的就是targetDataSources和defaultTargetDataSource,具体的初始化过程见afterPropertiesSet(),因为在通过setter设置数据源的时候,值类型不一定是DataSource,可能为字符串,这时候就需要dataSourceLookup将其转换为DataSource,dataSourceLookup一般情况下不需要我们自定义,直接使用默认的就行。

当需要操作数据库的时候,AbstractRoutingDataSource通过getConnection()方法获取当前需要操作的数据源的连接

@Override
public Connection getConnection() throws SQLException {
    return determineTargetDataSource().getConnection();
}

具体要使用哪个数据源,则由determineTargetDataSource()来决定

protected DataSource determineTargetDataSource() {
    Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
    // 这行是重点,决定当前的查找建,这个键需要与resolvedDataSources中的key对应
    Object lookupKey = determineCurrentLookupKey();
    DataSource dataSource = this.resolvedDataSources.get(lookupKey);
    if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
        // 使用默认数据源
        dataSource = this.resolvedDefaultDataSource;
    }
    if (dataSource == null) {
        throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
    }
    return dataSource;
}

其中,determineCurrentLookupKey()是个抽象方法

protected abstract Object determineCurrentLookupKey();

看到这里,大致的使用方式已经基本上很清晰了,接下来就来实现它

首先,自定义配置属性,用于配置多数据源

@ConfigurationProperties(prefix = "dynamic")
public class DynamicDataSourceProperties {
    private Map<String, DruidDataSource> datasource = new LinkedHashMap<>();

    public Map<String, DruidDataSource> getDatasource() {
        return datasource;
    }

    public void setDatasource(Map<String, DruidDataSource> datasource) {
        this.datasource = datasource;
    }
}

接下来创建配置类来对数据源进行配置

@EnableTransactionManagement
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
@Configuration
public class DynamicDataSourceConfig {

    private final DynamicDataSourceProperties dynamicDataSourceProperties;

    public DynamicDataSourceConfig(DynamicDataSourceProperties dynamicDataSourceProperties) {
        this.dynamicDataSourceProperties = dynamicDataSourceProperties;
    }

    /**
     * 默认数据源
     *
     * @return DataSource Bean
     */
    @Bean
    @ConfigurationProperties("spring.datasource.druid")
    public DataSource dataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    
      /**
     * 动态数据源
     * <p>
     * Primary 不能少
     *
     * @return DynamicDataSource Bean
     */
    @Primary
    @Bean
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(getDynamicDataSource());
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSource());
        return dynamicDataSource;
    }

    private Map<Object, Object> getDynamicDataSource() {
        Map<String, DruidDataSource> dataSourcePropertiesMap = dynamicDataSourceProperties.getDatasource();
        return new HashMap<>(dataSourcePropertiesMap);
    }
}

同时,因为使用了自定义数据源,所以需要去掉数据源的自动配置,在主启动类上的@SpringBootApplication注解上通过exclude属性将DataSourceAutoConfiguration排除,如下

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpringBootDynamicDatasourceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDynamicDatasourceApplication.class, args);
    }
}

回到配置类DynamicDataSourceConfig,其中的DynamicDataSource定义如下,其继承自AbstractRoutingDataSource并实现了determineCurrentLookupKey()方法来决定选用哪个查找键,此方法内则调用的是DynamicContextHolder.peek()来获取查找键。

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicContextHolder.peek();
    }
}

DynamicContextHolder主要通过ThreadLocal来保存当前线程的数据源,并且使用双端队列Deque来保存当前事务中涉及的到数据源,毕竟有些事务中涉及到多个数据源,比如最外层是数据源ds0,中层是ds1,内层是ds2,此时使用队列是非常合适的。

public class DynamicContextHolder {
    private static final ThreadLocal<Deque<String>> CONTEXT_HOLDER = ThreadLocal.withInitial(ArrayDeque::new);

    public static String peek() {
        return CONTEXT_HOLDER.get().peek();
    }

    public static void push(String dataSource) {
        CONTEXT_HOLDER.get().push(dataSource);
    }

    public static void poll() {
        Deque<String> deque = CONTEXT_HOLDER.get();
        deque.poll();
        if (deque.isEmpty()) {
            CONTEXT_HOLDER.remove();
        }
    }
}

接下来定义注解来标识使用哪个数据源

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

对应的切面

@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DataSourceAspect {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Pointcut("@annotation(com.example.annotation.DynamicDataSource) " +
            "|| @within(com.example.annotation.DynamicDataSource)")
    public void dataSourcePointCut() {

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Class<?> targetClass = point.getTarget().getClass();
        Method method = signature.getMethod();

        DynamicDataSource targetDataSource = targetClass.getAnnotation(DynamicDataSource.class);
        DynamicDataSource methodDataSource = method.getAnnotation(DynamicDataSource.class);
        if (targetDataSource != null || methodDataSource != null) {
            String value;
            if (methodDataSource != null) {
                value = methodDataSource.value();
            } else {
                value = targetDataSource.value();
            }

            DynamicContextHolder.push(value);
            logger.info(">>> set datasource success {}", value);
        } else {
            logger.info(">>> use default datasource...");
        }
        try {
            return point.proceed();
        } finally {
            DynamicContextHolder.poll();
        }
    }
}

在切面中,切点同时使用了@annotation和@within,前者是方法级别,用于拦截方法上的注解,后者是对象级别,用于拦截类上的注解。在设置数据源的时候,优先使用方法级别,其次才使用类级别。

接下来新建对应的库和测试表来进行测试。

create database if not exists `db0` default character set utf8mb4 collate utf8mb4_bin;
use `db0`;
create table if not exists user_info
(
    id   bigint primary key auto_increment,
    name varchar(64),
    age  tinyint
);

create database if not exists `db1` default character set utf8mb4 collate utf8mb4_bin;
use `db1`;
create table if not exists user_info
(
    id   bigint primary key auto_increment,
    name varchar(64),
    age  tinyint
);
create database if not exists `db2` default character set utf8mb4 collate utf8mb4_bin;
use `db2`;
create table if not exists user_info
(
    id   bigint primary key auto_increment,
    name varchar(64),
    age  tinyint
);

insert into db0.user_info(name, age) VALUE ('jack','18');
insert into db1.user_info(name, age) VALUE ('mary','18');
insert into db2.user_info(name, age) VALUE ('john','18');

创建对应的实体类和mybatis操作接口,代码略。

然后配置数据源

spring:
  # 默认数据源
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/db0?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
      username: root
      password: root

# 多数据源配置
dynamic:
  datasource:
    # 数据源1 dataSource01
    dataSource01:
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
      username: root
      password: root

    # 数据源2 dataSource02
    dataSource02:
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
      username: root
      password: root

接下来就可以测试了,有如下类,类中有三个方法,分别来更新三个数据源的数据的age字段,同时配置了事务的传播类型为REQUIRED,即若当前不存在事务,则创建新的事务,若存在,则加入当前事务。

@Slf4j
@Service
@DynamicDataSource
public class TestService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateDefault() {
        UserInfo info = new UserInfo().setId(1L).setAge(1);
        userInfoMapper.updateById(info);
        log.info("ds0: {}", userInfoMapper.selectById(info.pkVal()));
    }

    @DynamicDataSource("dataSource01")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateDS1() {
        UserInfo info = new UserInfo().setId(1L).setAge(2);
        userInfoMapper.updateById(info);
        log.info("ds1: {}", userInfoMapper.selectById(info.pkVal()));
    }

    @DynamicDataSource("dataSource02")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateDS2() {
        UserInfo info = new UserInfo().setId(1L).setAge(3);
        userInfoMapper.updateById(info);
        log.info("ds2: {}", userInfoMapper.selectById(info.pkVal()));
    }
}

有如下测试类

@SpringBootTest
public class SpringBootDynamicDatasourceApplicationTests {

    @Autowired
    TestService testService;

    @Rollback(false)
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Test
    public void test() {
        testService.updateDefault();
        testService.updateDS1();
        testService.updateDS2();
    }
}

按照理解的,执行完上述测试方法后,三个数据源对应的表中,id为1的数据的age应该分别被更新为1,2,3。

接下来就来执行它,执行之后,日志如下

image-20220425172419056

发现问题了,从绿色框中可以看到,切面起作用了,但是为何三个方法内打印的UserInfo都是ds0的呢,按理来说,后面两个不应该是ds1,ds2吗?问题出在哪呢?

有经验的大佬应该已经知道了,问题就出在事务的传播级别上,从图中也可以看出,事务的开启和关闭仅有一次,那就改变传播级别再来测试一下。

首先,可以知道的是,如果将测试方法上的事务去掉,那么TestService服务的三个方法会运行在各自的事务中,互不相关。验证一下,如下,注释掉测试方法上的事务注解,TestService不变

    @Rollback(false)
//    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Test
    public void test() {
        testService.updateDefault();
        testService.updateDS1();
        testService.updateDS2();
    }

执行后,日志如下,可以看到,数据源是切换了,结果是符合预期的,但是有一个大问题,三个方法分别运行在各自的事务中,这就无法保证一致性了,例如三个方法中前面的执行成功了,但是后面的执行失败了,那么前面的是不会回滚的(面试常问的事务失效场景之一)。

image-20220425173812153

为了验证这个问题,在上面的基础上,修改TestService的第三个方法updateDS2,让方法抛出一个异常

@DynamicDataSource("dataSource02")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void updateDS2() {
    UserInfo info = new UserInfo().setId(1L).setAge(3);
    userInfoMapper.updateById(info);
    log.info("ds2: {}", userInfoMapper.selectById(info.pkVal()));
    int i = 1/0;
}

再来执行一次(在重新执行测试方法之前,需要先将数据还原),日志如下。这时候再来查询数据库,会发现前两个没有回滚,但第三个回滚了,所以去掉测试方法上的事务注解显然是不可行的。

image-20220425175247927

同样的,如果恢复测试方法上的事务注解,但是将TestService的三个方法上的事务传播类型由REQUIRED改为REQUIRES_NEW,结果与上面的测试是类似的。虽然最外层有一个事务了,但是里面的三个方法分别开启了新事务,所以最后一个方法抛出的异常不会对前两个方法的事务产生影响。

也就是说,如果进入切面前存在事务,那么即便切面里面将数据源放入当前线程的ThreadLocal了,AbstractRoutingDataSource也不会进行切换。不信可以在自定义的实现类DynamicDataSource中的determineCurrentLookupKey方法里面打个断点试一下。

总结,AbstractRoutingDataSource切换数据源,适合目标方法(要切换数据源的方法)外层没有被事务包裹或目标方法运行于独立的事务之中才有效。

浅谈使用Spring多数据源路由AbstractRoutingDatasource实现动态切换数据源 使用Spring多数据源路由AbstractRoutingDatasource实现动态切换数据源 阅读详情

相关推荐

Spring的AbstractRoutingDataSource多数据源切换

spring实现多数据源切换示例讲解多数据源切换的使用场景maven坐标数据库准备sql脚本`(两个库各一个user表)`数据库配置文件`jdbc.properties`实体数据模型mapper准备mapper接口`UserMapper`mapper配置文件`UserMapper.xml`切换数据源实现连接池名称枚举`DataSourceType`连接池主键名称存取对象`DynamicDataSo...

博茨瓦纳的狮王 921

AbstractRoutingDataSource详解,分析多数据源切换原理

在spring中有一个抽象类AbstractRoutingDataSource类,通过这个类可以实现动态数据源切换。如下是这个类的成员变量 // 是存储将要切换的多数据源bean信息,一般是<beanName,DataSource-bean> private Map<Object, Object> targetDataSources; private Object defaultTargetDataSource; private Map<Object, DataSource

stay foolish 1万+

利用Spring的AbstractRoutingDataSource做多数据源动态切换

多数据源系列 1、spring boot2.0 +Mybatis + druid搭建一个最简单的多数据源 2、利用Spring的AbstractRoutingDataSource做多数据源动态切换 3、使用dynamic-datasource-spring-boot-starter做多数据源及源码分析 简介 搭建多数据源有多种方式,上一篇博客介绍了一种最基本的方式搭建多数据源,就是把每个数据源配置了一个DataSource的Bean,这种方式显得比较繁琐,mapper也要放在不同的地方,这里介绍一种动态切换

Hello World ^—^ 4643

Spring.动态数据源AbstractRoutingDataSource (分库组件,原理分析,源码,实现代码)

分析和设计 如果需要动态数据源,实现一个DataSource代理,在获取Connection时做手脚。 说明:一个请求进来,数据源对象不能变的,获取的Connection是每次都需要获取的。搞一个数据源代理对象,然后在getConnection方法返回不同数据源Connection。 AbstractRoutingDataSource Spring提供的版本 追getConnection方法: 看看protected DataSource determineTargetDat...

记录 分享 成就 5210

MyBatis 多数据源切换:AbstractRoutingDataSource 与拦截器对比及实现实战

MyBatis实现多数据源切换主要采用两种方案:基于Spring AbstractRoutingDataSource的动态路由和基于MyBatis拦截器的切换机制。前者通过继承AbstractRoutingDataSource重写determineCurrentLookupKey方法,利用ThreadLocal存储数据源标识,适合方法级别切换和Spring事务集成;后者通过拦截Executor的query/update方法,支持SQL语句级别的细粒度控制。

2301_76740633的博客 2953

【亲测可用!】阿里达摩院开源实时数字人对话VideoChat本地部署教程(8G显存可跑)

本文主要记录在部署阿里达摩院开源实时数字人对话VideoChat时遇到的问题,希望对各位技术开发或爱好者有所帮助!

波点兔的博客 3897

spring boot使用AbstractRoutingDataSource实现动态数据源切换

一、AbstractRoutingDataSource Spring boot提供了AbstractRoutingDataSource 根据用户定义的规则选择当前的数据源,这样我们可以在执行查询之前,设置使用的数据源。实现可动态路由的数据源,在每次数据库查询操作前执行。它的抽象方法 determineCurrentLookupKey() 决定使用哪个数据源。 org.springframework...

愿风裁尽尘中沙 7万+

springcloud+nacos+gateway+oauth2小聚会

在微服务工程中,Nacos作为目前主流的注册中心和配置中心,Spring Cloud Gateway作为目前主流的网关,下面引入spring security+oauth2+jwt作为认证和授权中心,进行简单的聊聊。

ldcaws的专栏 2646

spring AbstractRoutingDataSource详解,分析多数据源切换原理

1.在spring中有一个抽象类AbstractRoutingDataSource类,通过这个类可以实现动态数据源切换。如下是这个类的成员变量 private Map<Object, Object> targetDataSources; private Object defaultTargetDataSource; private Map<Object, DataSource...

咻pur慢 8521

3种六轴IMU姿态解算算法对比:互补滤波、Mahony与卡尔曼滤波性能实测

本文深入对比了三种六轴IMU姿态解算算法:互补滤波、Mahony与卡尔曼滤波的性能表现。通过实测数据分析了各算法在精度、计算复杂度和适用场景上的差异,为无人机、机器人等运动控制系统提供了选型建议。重点探讨了六轴陀螺仪与加速度传感器的数据融合技术,帮助开发者根据项目需求选择最优解算方案。

weixin_29054245的博客 337

【WRF数据准备】土地利用数据-MODIS MCD12Q1数据下载及制备

【WRF数据准备】MODIS静态地理数据下载及制备

WW、forever的博客 3413

AbstractRoutingDataSource实现多数据源切换以及事务中无法切换问题

为了实现数据源的动态切换,我们采用了AbstractRoutingDataSource结合AOP+反射来自定义注解。通过这种机制,我们可以在运行时根据自定义注解自动选择不同的数据源,从而实现灵活高效的数据访问策略。具体来说,我们首先创建了一个继承自AbstractRoutingDataSource的动态数据源类,该类能够管理多个数据源并根据线程上下文中的特定键值来选择使用哪一个数据源。接着,我们定义了一个自定义注解,用于标记需要切换数据源的方法或类。

胜人者有力,自胜者强! 3039

最大面积验证码通用解法

最大面积验证码、面积验证通用解法

九月镇灵将的博客 1044

SpringBoot+AbstractRoutingDataSource实现多数据源以及事务处理

spring框架中,spring-jdbc模块提供了AbstractRoutingDataSource,其内部可以包含了多个DataSource,然后在运行时来动态的访问哪个数据库。这种方式访问数据库的架构图如下所示:应用直接操作的是AbstractRoutingDataSource的实现类,告诉AbstractRoutingDataSource访问哪个数据库,然后由AbstractRoutingDataSource从事先配置好的数据源(ds1、ds2)选择一个,来访问对应的数据库。

qq_22772699的博客 3278

AI驱动芯片设计的端到端验证:AI应用架构师的全流程指南

想象你要建造一座1000层的超级摩天大楼,每个房间都有独特的功能,管道、电路、电梯系统交织如迷宫。传统的检查方式是派1000个工程师逐层逐房手动检查,耗时十年且仍可能遗漏火灾隐患。这就是今天芯片设计面临的困境:7nm芯片含百亿晶体管,相当于百亿个"房间",传统验证方法(人工编写测试用例、随机仿真)已难以应对。本文的目的,是为AI应用架构师提供一份"AI驱动芯片验证导航图",范围涵盖从验证需求分析到芯片签核的全流程,包括AI模型如何融入传统验证工具链、数据如何驱动验证效率提升、以及端到端闭环系统的构建方法。

2501_92132293的博客 1241

STM32 实现 4*4 矩阵键盘扫描(HAL库、标准库 都适用)

本文实现的代码是基于STM32HAL库的基础上的,不过标准库也可以用,只是调用的库函数不同,逻辑跟配置是一样的,按我这里的逻辑来配置即可。 1、键盘原理图: 原理举例:先把 F0-F7 内部拉高,这样这个8个引脚都是高电平,然后就进行列扫描。例如:假如按下3按钮,Y3 列扫描,把F4先拉低,然后读取F0-F3的状态,就会读出为1110,这就可 以知道是F3行拉低了,同时这时候是程序控制F4拉低的,这样就可以知道是F4列导致它转态变化了的,这样就可以定位出是F4列F3行的按键按下了;其他的列也是这样子扫描

lhh_qrsly的博客 7058

使用Spring的AbstractRoutingDataSource类实现多数据源切换

最近因为项目需要在做两个项目间数据同步的需求,具体是项目1的数据通过消息队列同步到项目2中,因为这个更新操作还涉及到更新多个库的数据,所以就需要多数据源切换的操作。下面就讲讲在Spring中如何进行数据源切换。这里是使用AbstractRoutingDataSource类来完成具体的操作,AbstractRoutingDataSource是Spring2.0后增加的。 QQ截图20170211220044.jpg 实现数据源切换的功能就是自定义一个类扩展AbstractRoutingDa..

疯一样的女子 585

基于YOLOv10深度学习的花生种子霉变检测系统

YOLO(You Only Look Once)是当前最先进的目标检测算法之一,具有快速、精准的特性。YOLOv10是YOLO系列的最新版本,相较于之前的版本,YOLOv10在特征提取、模型精度和速度上都有了显著的提升。YOLOv10采用了更深的卷积神经网络、更多的跨层特征融合方法,使得其在不同尺寸物体的检测和复杂场景的处理上都表现出了优异的性能。YOLOv10特别适合应用在需要快速处理并检测大量图像的任务中,如花生种子霉变检测等,能够实现精准、高效的检测。

2201_76125393的博客 648

【mysql】使用AbstractRoutingDataSource实现多数据源 与 获取mapper上注解

随着业务发展速度越来越快,数据的增长也呈现倍数级别增长,数据库的压力,对于查询和写入等所有操作,都依赖于主库,其实有一些对于时效性要求不高的场景,无需使用主库查询,可以使用从库来分摊主库的压力,提升数据库集群整体的吞吐量。

Old Wang的博客 1264

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

数据库轻松切换:解读Spring中的AbstractRoutingDataSource

本文将深入探讨Spring框架中的AbstractRoutingDataSource,这是实现多数据源动态切换的关键组件。我们将详细介绍AbstractRoutingDataSource的原理、使用方法和实际应用场景,帮助读者更好地理解和使用这一重要功能。

todoitbo的博客 1万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Spring-AbstractRoutingDataSource

注:spring提供了一个多数据源解决方案:AbstractRoutingDataSource。最近项目用到了多数据源。简单教练一下这个类,做个学习笔记。 从继承上看,AbstractRoutingDataSource继承AbstractDataSource。AbstractDataSource实现DataSource接口。那么AbstractRoutingDataSource就是一批DataSource实例的集合体。 操作数据库首先获取Connection。AbstracRoutingDataSour

xiaopang2020的博客 994

Mybatis多数据源的切换——AbstractRoutingDataSource

Spring数据源路由核心类AbstractRoutingDataSource,API文档解释如下: Abstract javax.sql.DataSource implementation that routes getConnection() calls to one of various target DataSources based on a lookup key. The latt...

天天向上 1356

Spring+MyBatis多数据源配置实现(AbstractRoutingDataSource)

在spring 中,一个很好用但是容易被忽略的,就是AbstractRoutingDataSource,它的一个作用就是可以根据用户发起的不同请求去转换不同的数据源,比如根据用户的不同地区语言选择不同的数据库,下面举例说明:  单数据源时的Spring配置文件 xml version="1.0" encoding="UTF-8"?> beans xmlns="http://w

马万明的专栏 3118

【Spring】使用Spring的AbstractRoutingDataSource实现多数据源切换

多数据源切换

weknow 441

Spring boot 使用AbstractRoutingDataSource实现数据源动态切换

Spring boot提供了AbstractRoutingDataSource 根据用户定义的规则选择当前的数据源,这样我们可以在执行查询之前,设置使用的数据源。实现可动态路由的数据源,在每次数据库查询操作前执行。它的抽象方法 determineCurrentLookupKey() 决定使用哪个数据源。

Isonion的博客 2647

使用Spring的AbstractRoutingDataSource实现动态数据源

前言 笔者公司目前数据库进行了分库操作,分成了几个库,存放用户相关信息的user库,存放资产信息的asset库,存放直播相关信息的live库。在平时开发过程中涉及多库操作的地方,需要通过rpc调用对应服务。这样的开发模型大体上没问题,因为既然拆分库了,应用跟随数据库进行拆分,也能防止以后开发代码混乱。但是这样缺少了灵活性,所以我这里为我们项目增添多数据源功能。 调研 调研了两种spring+mybatis数据源方案。 1 多份配置 在项目中,为每个库分别设置一套数据源配置。 DataSource,SqlSe

https://gitee.com/hello-piper/PiperChat 1864
上一篇: 浅析可重入锁的加锁释放锁过程
下一篇: maven打包时跳过测试,并打包源码和文档
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值