精华内容
下载资源
问答
  • spring:datasource:master:password: erp_test@abcurl: jdbc:mysql://127.0.0.1:3306/M201911010001?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&...

    spring:

    datasource:

    master:

    password: erp_test@abc

    url: jdbc:mysql://127.0.0.1:3306/M201911010001?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true

    driver-class-name: com.mysql.jdbc.Driver

    username: erp_test

    type: com.alibaba.druid.pool.DruidDataSource

    druid:

    initial-size: 5

    max-active: 150

    min-idle: 10

    max-wait: 6000

    web-stat-filter.enabled: true

    stat-view-servlet.enabled: true

    timeBetweenEvictionRunsMillis: 60000

    minEvictableIdleTimeMillis: 300000

    validationQuery: SELECT 'x'

    testWhileIdle: true

    testOnBorrow: false

    testOnReturn: false

    poolPreparedStatements: true

    maxPoolPreparedStatementPerConnectionSize: 20

    filters: stat,wall,log4j

    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

    useGlobalDataSourceStat: true

    cluster:

    - key: slave1

    password: erp_test@abc

    url: jdbc:mysql://127.0.0.1:3306/M201911010002?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true

    idle-timeout: 20000

    driver-class-name: com.mysql.jdbc.Driver

    username: erp_test

    type: com.alibaba.druid.pool.DruidDataSource

    druid:

    initial-size: 5

    max-active: 150

    min-idle: 10

    max-wait: 6000

    web-stat-filter.enabled: true

    stat-view-servlet.enabled: true

    timeBetweenEvictionRunsMillis: 60000

    minEvictableIdleTimeMillis: 300000

    validationQuery: SELECT 'x'

    testWhileIdle: true

    testOnBorrow: false

    testOnReturn: false

    poolPreparedStatements: true

    maxPoolPreparedStatementPerConnectionSize: 20

    filters: stat,wall,log4j

    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

    useGlobalDataSourceStat: true

    - key: slave2

    password: erp_test@abc

    url: jdbc:mysql://127.0.0.1:3306/M201911010003?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true

    idle-timeout: 20000

    driver-class-name: com.mysql.jdbc.Driver

    username: erp_test

    type: com.alibaba.druid.pool.DruidDataSource

    druid:

    initial-size: 5

    max-active: 150

    min-idle: 10

    max-wait: 6000

    web-stat-filter.enabled: true

    stat-view-servlet.enabled: true

    timeBetweenEvictionRunsMillis: 60000

    minEvictableIdleTimeMillis: 300000

    validationQuery: SELECT 'x'

    testWhileIdle: true

    testOnBorrow: false

    testOnReturn: false

    poolPreparedStatements: true

    maxPoolPreparedStatementPerConnectionSize: 20

    filters: stat,wall,log4j

    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

    useGlobalDataSourceStat: true

    展开全文
  • 一:流程图解灵活动态切换数据源,每次在执行一个Dao操作之前可以设置当前的数据源。二:实现原理1、扩展Spring的AbstractRoutingDataSource抽象类(该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值...

    一:流程图解

    灵活动态的切换数据源,每次在执行一个Dao操作之前可以设置当前的数据源。

    二:实现原理

    1、扩展Spring的AbstractRoutingDataSource抽象类(该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上。)

    从AbstractRoutingDataSource的源码中

    我们可以看到,它继承了AbstractDataSource,而AbstractDataSource不就是javax.sql.DataSource的子类,So我们可以分析下它的getConnection方法:

    获取连接的方法中,重点是determineTargetDataSource()方法,看源码:

    上面这段源码的重点在于determineCurrentLookupKey()方法,这是AbstractRoutingDataSource类中的一个抽象方法,而它的返回值是你所要用的数据源dataSource的key值,有了这个key值,

    resolvedDataSource(这是个map,由配置文件中设置好后存入的)就从中取出对应的DataSource,如果找不到,就用配置默认的数据源。

    看完源码,应该有点启发了吧,没错!你要扩展AbstractRoutingDataSource类,并重写其中的determineCurrentLookupKey()方法,来实现数据源的切换:

    public class DynamicDataSource extendsAbstractRoutingDataSource {/*** override determineCurrentLookupKey

    * Description: 自动查找datasource*/@OverrideprotectedObject determineCurrentLookupKey() {//从自定义的位置获取数据源标识

    returnDynamicDataSourceHolder.getDataSource();

    }

    }

    DynamicDataSourceHolder这个类则是我们自己封装的对数据源进行操作的类:

    public classDynamicDataSourceHolder {/*** 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰*/

    private static final ThreadLocal THREAD_DATA_SOURCE = new ThreadLocal();

    //获取数据源public staticString getDataSource() {returnTHREAD_DATA_SOURCE.get();

    }

    //设置数据源public static voidsetDataSource(String dataSource) {

    THREAD_DATA_SOURCE.set(dataSource);

    }

    //清空数据源public static voidclearDataSource() {

    THREAD_DATA_SOURCE.remove();

    }

    }

    那么setDataSource方法要在什么地方执行呢?

    我们可以应用Spring aop来设置,把配置的数据源类型都设置成注解标签,在Servive层中需要切换数据源的方法上,写上注解标签,调用相应的方法切换数据源

    @DataSource(name=DataSource.slave1)public List getProducts(){

    import java.lang.annotation.*;

    @Target({ElementType.METHOD,ElementType.TYPE})

    @Retention(RetentionPolicy.RUNTIME)

    @Documentedpublic @interfaceDataSource{

    String name()defaultDataSource.master;public static String master="datasource1";public static String slave1="datasource2";

    publidstatic String slave2="datasource3";

    }

    三:配置文件

    项目中单独分离出application-database.xml,关于数据源配置的文件

    配置多数据源映射关系

    SessionFactory的配置还是照旧,使用以前的配置,只不过当前选择的数据源是datasource,也就是数据源选择的中间层MultipleDataSourceToChoose,因为当前的中间层中实现了DataSource这个接口,所以可以看做为DataSource的是实现类啦,所以配置不会出现问题。

    使用AOP拦截特定的注解去动态的切换数据源

    @Order(1)如果有多个拦截器时,第一个执行

    @Aspect

    @Slf4j

    @Component

    @Order(1)public classDataSourceAop {//@within在类上进行设置//@annotation 在方法上进行设置

    @Pointcut("@within(com.zmeng.rinascimento.caravaggio.common.util.datasource.DataSource)||@annotation(com.zmeng.rinascimento.caravaggio.common.util.datasource.DataSource)")public voidpointcut(){}

    @Before("pointcut()")public void doBefore(JoinPoint joinPoint)throwsException{

    Class clazz=joinPoint.getTarget().getClass();

    String methodName=joinPoint.getSignature().getName();

    Class[] parameterTypes=((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();

    Method method=clazz.getMethod(methodName,parameterTypes);//获取方法上的注解

    DataSource dataSource = method.getAnnotation(DataSource.class);if(dataSource==null){//获取类上的注解

    dataSource = joinPoint.getTarget().getClass().getAnnotation(DataSource.class);if(dataSource==null){return;

    }

    }//获取注解上的数据源信息

    String dataSourceKey =dataSource.value();if(dataSourceKey!=null){//给当前执行SQL操作设置特殊的数据源的信息

    DynamicDataSourceHolder.setDataSource(dataSourceKey);

    System.out.println(DynamicDataSourceHolder.getDataSource());

    }

    log.info("AOP动态切换数据源,className"+joinPoint.getTarget().getClass().getName()+"methodName"+method.getName()+";dataSourceKey:"+dataSourceKey==""?"默认数据源":dataSourceKey);

    }

    @After("pointcut()")public voidafter(JoinPoint joinPoint){//清理掉当前的数据源,让默认的数据不受影响

    System.out.println(DynamicDataSourceHolder.getDataSource());

    DynamicDataSourceHolder.clearDataSource();

    }

    }

    如果不使用aop进行拦截切换数据源,也可以在代码中进行手动的切换数据源

    DynamicDataSourceHolder.setDataSource("dataSource");

    展开全文
  • Java动态切换数据源(AOP)

    千次阅读 2021-02-25 19:37:07
    一、对比通过中间层来管理数据源,常用的有 mycat 等,但有一个大缺陷,就是性能的损耗,即本身直接请求数据库的事儿,却要经过中间层来进行一次分配的操作,但是,通用性比较高。而使用客户端模式来管理数据源,直...

    一、对比

    通过中间层来管理数据源,常用的有 mycat 等,但有一个大缺陷,就是性能的损耗,即本身直接请求数据库的事儿,却要经过中间层来进行一次分配的操作,但是,通用性比较高。

    而使用客户端模式来管理数据源,直连数据库,就没有那一部分的性能损耗,但是不够通用,而且如果业务足够复杂时,对数据库的连接处理也并不 easy。

    二、实现 ①自定义数据源

    目录结构概览:

    b12337004bd79c317bf023841ed725bd.png

    采用 springboot 来实现本操作,所以下文见到的都是注解的形式。

    ① 配置两个数据源

    db3d02ffd0bcf4c3b082e448df724df4.png

    01469ce533a02db267de73f9180f16a5.png

    ② 使用 ThreadLocal 保存数据源,目的是保证当前数据源在当前线程中不被其它线程修改

    bdb9c598a6f0503ef402d570a8b19256.png

    ③ 写个动态数据源的实现,需要继承 Spring 给我们提供的 AbstractRoutingDataSource 抽象类

    其实就是个路由。

    fc893a7a0da80b94f9d254d7f963b62c.png

    ④ 完成动态数据源的对象的申明 (bean)

    73f35a1fa6da9b8a8fd1be4ccf20ba83.png

    三、实现 ②自定义AOP

    申明一个 AOP 切面,我们的做法是在 repository 层进行数据源的切换,完成后移除数据源的名称。

    a44dae04b5ad9cc497f6f85af38af655.png

    四、实现 ③动态切换

    ① 自定义注解,该注解使用目标是 dao 层方法

    c14d1467199a6c2261e998763f11f639.png

    ② dao 层方法上加注解,没有加的就使用默认的 数据库连接

    98244dca5185c08a965b104f87a9a272.png

    五、测试效果

    ① 自定义实体类

    ac3af4209a691a87ca907ea1953f1fec.png

    ② 写测试类,查十次,奇数次查默认数据库,否则查 test2 数据库

    ③ 结果,如下图,在查 test2 数据库的时候,进行了连接处的初始化动作

    7e75e9d76cc7d5776f1b4370c65a76b6.png

    六、总结

    本文采用的是 Spring 中的 AbstractRoutingDataSource和 AOP来实现动态数据源的切换,如此简单的操作可以满足大部分基础的切换动作。

    展开全文
  • 前言前几天在做一个项目的时候遇到的一个问题,在事务中动态切换数据源报错,于是上网百度了一下@Transaction注解的执行逻辑,然后才恍然大悟....调用链事务代码调用链:service注解上@transactional-->...

    前言

    前几天在做一个项目的时候遇到的一个问题,在事务中动态切换数据源报错,于是上网百度了一下@Transaction注解的执行逻辑,然后才恍然大悟....

    调用链

    事务代码调用链:

    service注解上@transactional-->TransactionInterceptor.interpter()-->TransactionAspectSupport.createTransactionIfNecessary()-->AbstractPlatformTransactionManager.getTransaction()-->DataSourceTransactionManager.doBegin()-->AbstractRoutingDataSource.determineTargetDataSource()[lookupKey==null去拿默认的Datasource, 不为空则使用获取到的连接]

    -->DataSourceTransactionManager.setTransactional()[将连接设置到TransactionUtils的threadLocal中]

    --->Repository@Annotation-->执行一般调用链, 问题在于SpringManagedTransaction.getConnection()

    -->openConnection()

    -->DataSourceUtils.getConnection()

    -->TransactionSynchronizationManager.getResource(dataSource)不为空[从TransactionUtils的threadLocal中获取数据源], 所以不会再去调用DynamicDataSource去获取数据源

    问题分析与解决

    从这里可以看出来,每次都会从threadLocal中去拿数据源,如果为空,就创建新的连接,如果不为空的话直接复用,而threadLocal是线程型的变量,只要在同一个中,就只会存在一个,所以这就会导致你切换数据源失败,因为threadLocal不为空。

    解决方案

    你可以把threadLocal变量给remove掉,不过threadLocal是private是私有的,可以根据反射修改,网上有一套解决方案,有点麻烦。

    因为我的场景是在一个事务中mysql写,而sqlserver读,所以sqlserver实质上不需要事务,所以我新开了一个线程来获取sqlserver的值,搭配futureTask来获取异步的返回值(get阻塞),这样就可以实现了(因为新开了一个线程之后threadLocal就是null了)

    这里还会存在一个问题,假设你使用的是线程连接池的话,还要考虑一下工作线程复用的情况(这样也会导致threadLocal不为空)

    最好的办法应该就是分布式事务的处理,不过我还不太了解...

    展开全文
  • 主从数据源动态切换

    2021-02-11 20:23:26
    先做一个小Demo测试数据源动态切换。主要使用切面修改配置文件实现数据源切换,再切点后置通知中再切回主数据源。引入依赖xsi:schemaLocation=...
  • Springboot+Druid动态切换数据源一、描述二、实现2.1 maven引入jar2.2 数据源上下文DataSourceContextHolder2.3 DynamicDataSource继承AbstractRoutingDataSource抽象类2.4 Druid配置类2.2 DruidDataSourceUtil实现...
  • SpringBoot动态切换数据源-快速集成多数据源的启动器
  • 当一个项目中有多个数据源(也可以是主从库)的时候,我们可以利用注解在mapper接口上标注数据源,从而来实现多个数据源在运行时的动态切换。实现原理在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了...
  • Springboot动态切换数据源

    千次阅读 2021-11-30 10:31:31
    动态切换数据源 在springboot项目中只需一句代码即可实现多个数据源之间的切换: // 切换sqlserver数据源: DataSourceContextHolder.setDataBaseType(DataSourceEnum.SQLSERVER_DATASOURCE); ...... // 切换mysql数据...
  • 首先在application.yml 文件... 模块代码下载地址 springboot根据用户动态切换数据源java代码实现-Java文档类资源-CSDN下载springboot根据用户动态切换数据源java代码实现更多下载资源、学习资料请访问CSDN下载频道....
  • mybatis动态切换数据源

    2021-01-14 16:04:13
    (#)背景:由于业务的需求,导致需要随时切换15个数据源,此时不能low逼的去写十几个mapper,所以想到了实现一个数据源动态切换首先要想重写多数据源,那么你应该理解数据源的一个概念是什么,...接下来我们要介绍一下...
  • 1. **多DataSource + 多SqlSessionFactory** 在使用Dao层的...2. **使用AbstractRoutingDataSource的实现类通过AOP或者手动处理实现动态的使用我们的数据源**, 基于这种方式,不仅可是实现真正意义上的`多数据源
  • 在学习的过程中发现没有文章将这些方式和常见的问题集中处理,所以将常用的方式和常见的问题都写在了在本项目的不同分支上:master: 使用了多数据源的 RESTful API 接口,使用 Druid 实现了 DAO 层数据源动态切换和...
  • 首先在yml文件配置多个数据源 spring: datasource: dynamic: # 是否开启 SQL日志输出,生产环境建议关闭,有性能损耗 p6spy: true hikari: connection-timeout: 30000 max-lifetime: 1800000 max-pool-...
  • 此时可以根据数据源动态创建新的SqlSessionFactory实例,而不是在启动过程中创建的单例。对应的代码如下,主要有两点 大体逻辑直接从org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration#...
  • 所以涉及到需要在一个项目中配置多数据源,并且能够动态切换。经过一番摸索,完美实现动态切换,记录一下配置方法供大家参考。设计总体思路Spring-Boot+AOP方式实现多数据源切换,继承AbstractRoutingDataSource实现...
  • 今天我们来简单介绍一些如何在程序中实现动态切换数据源,可能某台服务器性能比较好,让流量多的方法执行切换到此数据源去操作等等。 当然这种思想也可以扩展实现为读写分离,主库(主数据源)只负责写操作,从库(从...
  • SpringBoot 配置多数据源动态切换 1.实现思路 DataSource是和线程绑定的,动态数据源的配置主要是通过继承AbstractRoutingDataSource类实现的,实现在AbstractRoutingDataSource类中的 protected Object ...
  • useSSL=false&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&allowMultiQueries=true username: password: 方法上加: 同一个方法中进行数据源切换: DynamicDataSourceContextHolder.push("mysql");...
  • Spring Boot 构建多租户Saas软件架构,实现动态切换数据源概述应用场景维护、识别和路由租户数据源项目构建 概述 SaaS(Software as a Service),即多租户(或多承租)软件应用平台。 它只是一种软件架构,并没有...
  • 要实现多租户动态加载、切换数据源,并进行分表操作。 表结构参考: CREATE TABLE `tenant_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `TENANT_ID` varchar(255) DEFAULT NULL COMMENT '租户id', `...
  • 前言最近需要实现一个功能,动态刷新线上数据源环境,下面来使用Apollo配置中心和Spring提供的AbstractRoutingDataSource来实现。具体实现Apollo是携程开源的统一配置中心,和springboot无缝衔接并且不需要安装其他...
  • SpringBoot实现多数据源动态数据源自由切换 业务场景 在开发中,可能涉及到在用户的业务中要去查询对应订单的数据,而用户和订单又是分处于不同的数据库的,这样的业务该怎么处理呢? 这种就是多数据源的场景,...
  • SpringBoot多数据源动态切换

    千次阅读 2021-02-22 12:02:07
    创建数据库和数据表 首先需要建立两个库进行测试,我这里使用的是...-- 添加druid数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter&
  • //根据数据源得到数据,动态创建数据源bean 并将bean注册到applicationContext中去 while(iter.hasNext()) {//bean ID String beanKey =iter.next();//创建bean bdb =BeanDefinitionBuilder.rootBeanDefinition...
  • 听说爱点赞的人都月瘦十斤,月入十万哟!自从接触了JAVA,真的是每天都学到...通过百度查询 关键字:springboot 多数据源,给出的例子基本都是多套源策略,什么是多套源呢,看下图:多套源策略1.png这种策略虽然简单、直接...
  • AOP 实现多数据源切换 1、数据源配置 # 数据源配置 spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver druid: # 主库数据源 master: url: jdbc:...
  • 使用注解切换数据源 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Datasource { /** 数据源的值 @return */ String value() default “”; } yml配置数据源 datasource: ...
  • 数据源动态切换、跨库事物失效问题解决方案

    千次阅读 热门讨论 2021-04-09 18:18:45
    数据源动态切换、跨库事物失效问题解决方案一、问题出现的场景二、跨库事物失效的原因三、解决方案1、自定义跨库事物注解2、对有标记的请求、保存数据库链接、关闭自动提交3、对开启了跨库事物方法进行拦截、标记、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 317,664
精华内容 127,065
关键字:

动态切换数据源方法