点击上方“Java程序员聚集地”关注我们吧!

废话不多说直接上代码

pom文件的引入:记得一定要用阿里的镜像哦,不然下载速度会让你崩溃

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0modelVersion>    <groupId>com.gbiccgroupId>    <artifactId>demoartifactId>    <version>1.0-SNAPSHOTversion>     <parent>        <groupId>org.springframework.bootgroupId>        <artifactId>spring-boot-starter-parentartifactId>        <version>2.1.1.RELEASEversion>        <relativePath />    parent>      <properties>        <mybatis-spring-boot>1.3.4mybatis-spring-boot>        <mysql-connector>5.1.39mysql-connector>        <java.version>1.8java.version>        <oracle.version>11.2.0.3oracle.version>        <druid.version>1.1.14druid.version>        <mybatis.spring.boot.starter.version>1.3.2mybatis.spring.boot.starter.version>    properties>     <dependencies>        <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starterartifactId>        dependency>                 <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starter-webartifactId>        dependency>                 <dependency>            <groupId>com.alibabagroupId>            <artifactId>druid-spring-boot-starterartifactId>            <version>${druid.version}version>        dependency>          <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starter-aopartifactId>        dependency>                   <dependency>            <groupId>mysqlgroupId>            <artifactId>mysql-connector-javaartifactId>            <scope>runtimescope>        dependency>                 <dependency>            <groupId>com.oraclegroupId>            <artifactId>ojdbc6artifactId>            <version>${oracle.version}version>        dependency>                 <dependency>            <groupId>org.mybatis.spring.bootgroupId>            <artifactId>mybatis-spring-boot-starterartifactId>            <version>${mybatis-spring-boot}version>        dependency>                 <dependency>            <groupId>org.springframeworkgroupId>            <artifactId>spring-context-supportartifactId>        dependency>                 <dependency>            <groupId>org.projectlombokgroupId>            <artifactId>lombokartifactId>        dependency>                 <dependency>            <groupId>ch.qos.logbackgroupId>            <artifactId>logback-classicartifactId>        dependency>                 <dependency>            <groupId>org.slf4jgroupId>            <artifactId>jcl-over-slf4jartifactId>        dependency>    dependencies>         <pluginRepositories>        <pluginRepository>            <id>publicid>            <name>aliyun nexusname>            <url>http://maven.aliyun.com/nexus/content/groups/public/url>            <releases>                <enabled>trueenabled>            releases>            <snapshots>                <enabled>falseenabled>            snapshots>        pluginRepository>    pluginRepositories>     <build>        <plugins>            <plugin>                <groupId>org.springframework.bootgroupId>                <artifactId>spring-boot-maven-pluginartifactId>                <configuration>                    <fork>truefork>                 configuration>            plugin>        plugins>    build>project>

我的配置使用的yml文件,当然application.properties也是可以的

server:  port: 80spring:  application:    name: demo  datasource:    ## test1 database    test1:      jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:zwsj      username: user_frame2      password: user_frame2      driverClassName: oracle.jdbc.OracleDriver    test2:      jdbc-url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8      username: root      password: root      driver-class-name: com.mysql.jdbc.Driver#mybatis配置mybatis:  # 搜索指定包别名  typeAliasesPackage: com.gbicc.demo.**.domain  # 配置mapper的扫描,找到所有的mapper.xml映射文件  mapperLocations: classpath:mybatis/**/*Mapper.xml  # 加载全局的配置文件  configLocation: classpath:mybatis/mybatis-config.xml

多数据源配置动态加载

import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import javax.sql.DataSource;import java.util.HashMap;import java.util.Map; @Configuration@MapperScan(basePackages = "com.gbicc.demo.mapper",sqlSessionFactoryRef = "SqlSessionFactory")public class DataSourceConfig {      //bean创建对象,交给spring管理    @Bean(name = "test1DataSource")    @Primary//指定那个为主数据源    @ConfigurationProperties(prefix = "spring.datasource.test1")//绑定配置文件中的属性到bean中    public DataSource getDateSource1(){        return DataSourceBuilder.create().build();    }     @Bean(name = "test2DataSource")    @ConfigurationProperties(prefix = "spring.datasource.test2")//读取的数据源前缀, 跟yml文件对应    public DataSource getDateSource2(){        return DataSourceBuilder.create().build();    }      @Bean(name = "dynamicDataSource")    public DynamicDataSource DataSource(@Qualifier("test1DataSource")DataSource test1datasource,                        @Qualifier("test2DataSource")DataSource test2datasource ){        Map targetDataSources = new HashMap<>();        targetDataSources.put(DataBaseType.TEST01,test1datasource);        targetDataSources.put(DataBaseType.TEST02,test2datasource);        DynamicDataSource dataSource=new DynamicDataSource();        dataSource.setTargetDataSources(targetDataSources);        dataSource.setDefaultTargetDataSource(test1datasource);        return dataSource;    }     @Bean(name = "SqlSessionFactory")    public SqlSessionFactory test1SqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)            throws Exception{        SqlSessionFactoryBean bean=new SqlSessionFactoryBean();        bean.setDataSource(dynamicDataSource);        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/**/*Mapper.xml"));        return bean.getObject();    }
接下来配置一个最重要的一个类,
继承AbstractRoutingDataSource 抽象类,并重写determineCurrentLookupKey()方法,AbstractRoutingDataSource 类中determineCurrentLookupKey方法的key为数据源的名称,value为动态的数据源,determineCurrentLookupKey该类中还有一个非常重要的属性:private Map<Object, Object> targetDataSources;这个属性是会将你的数据源对象接受,然后设置给datasource类。
package com.gbicc.demo.config; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  import javax.sql.DataSource;import java.util.Map; /**\ * 定义一个动态数据源: * 继承AbstractRoutingDataSource 抽象类,并重写determineCurrentLookupKey()方法 */public class DynamicDataSource extends AbstractRoutingDataSource  {     @Override    protected Object determineCurrentLookupKey() {        DataBaseType dataBaseType = DataSourceType.getDataBaseType();        return dataBaseType;    }}

创建DataSourceType类 当然更多人喜欢用DynamicDataSourceContextHolder进行命名,这里我用了DataSourceType,名称随意,对程序的运行没有影响的。该类的作用就是创建一个安全的线程,然后将数据源放置进去。

   public class DataSourceType {    // 使用ThreadLocal保证线程安全    private static final ThreadLocal TYPE = new ThreadLocal();     // 往当前线程里设置数据源类型    public static void setDataBaseType(DataBaseType dataBaseType) {        if (dataBaseType == null) {            throw new NullPointerException();        }        System.err.println("[将当前数据源改为]:" + dataBaseType);        TYPE.set(dataBaseType);    }     // 获取数据源类型    public static DataBaseType getDataBaseType() {        DataBaseType dataBaseType = TYPE.get() == null ? DataBaseType.TEST01 : TYPE.get();        System.err.println("[获取当前数据源的类型为]:" + dataBaseType);        return dataBaseType;    }     // 清空数据类型    public static void clearDataBaseType() {        TYPE.remove();    }}

创建一个枚举类。名称必须要和yml配置文件中的名字保持一直,否则无法加载

package com.gbicc.demo.config; public enum DataBaseType {    TEST01, TEST02}

ok,到此多数据就配置完成了,接下来要配置AOP进行扫描注解。

DataSource这个注解吧,我是这么写的,好几种配置方式。我给大家举例三种方式吧,看你的具体场景使用,然后具体的使用。

第一种配置方式:

package com.gbicc.demo.config; import java.lang.annotation.*; /** * 切换数据注解 可以用于类或者方法级别 方法级别优先级 > 类级别 */@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface DataSource {    public DataBaseType value() default DataBaseType.TEST01; //该值即key值,默认使用默认数据库}

配置AOP拦截,不然注解无法使用。

package com.gbicc.demo.config; import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component; @Aspect@Componentpublic class DynamicDataSourceAspect {    @Before("@annotation(dataSource)")//拦截我们的注解    public void changeDataSource(JoinPoint point, DataSource dataSource) throws Throwable {        DataBaseType value = dataSource.value();        if (value.equals(DataBaseType.TEST01)){            DataSourceType.setDataBaseType(DataBaseType.TEST01);        }else if (value.equals(DataBaseType.TEST02)){            DataSourceType.setDataBaseType(DataBaseType.TEST02);        }else {            DataSourceType.setDataBaseType(DataBaseType.TEST01);//默认使用主数据库        }     }     @After("@annotation(dataSource)") //清除数据源的配置    public void restoreDataSource(JoinPoint point, DataSource dataSource) {        DataSourceType.clearDataBaseType();      }}

OK,这样就算配置完成了。

使用的时候这么用就行,这个注解可以作用在类中,也是以作用再方法中。

@DataSource(value = DataBaseType.TEST02)   @DataSource(value = DataBaseType.数据库名称)
  @DataSource(value = DataBaseType.TEST02)    public Integer test02hello(){        return demoMapper.hello();    }    @DataSource(value = DataBaseType.TEST01)    public Integer test01hello(){        return demoMapper.hello();    }

这是我的mapper层的代码:我的mysql和oracle都有一张sys_user表。

<?xml version="1.0" encoding="UTF-8" ?>/span>PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.gbicc.demo.mapper.DemoMapper">    <select id="hello" resultType="Integer">        SELECT COUNT(*) FROM sys_user    select>mapper>

第二种配置方式就比较简单粗暴了。

直接上代码:

package com.gbicc.demo.config; import org.springframework.stereotype.Component;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;  @Aspect@Componentpublic class DataSourceAop {    @Before("execution(* com.gbicc.demo.service.Impl..*.test01*(..))")    public void setDataSource2test01() {        System.err.println("test01业务");        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.TEST01);    }    @Before("execution(* com.gbicc.demo.service.Impl..*.test02*(..))")    public void setDataSource2test02() {        System.err.println("test02业务");        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.TEST02);    }}

直接AOP扫描包,不再使用自定义注解,当然这个时候记得将DynamicDataSourceAspect删除了。这个时候把,切换数据源就要写代码了,在你的方法需要切换数据源的地方要这么写:

public Integer test02hello(){   DataSourceType.setDataBaseType(DataBaseType.TEST01) return demoMapper.hello(); }

我的上面AOP的扫描注解包是直接扫面test02开头的方法查询的从表数据库,test01开头的查询的主表库。

16:51:29.503 [main] INFO  o.a.c.h.Http11NioProtocol - [log,173] - Starting ProtocolHandler ["http-nio-80"]16:51:29.510 [main] INFO  o.a.t.u.n.NioSelectorPool - [log,173] - Using a shared selector for servlet write/read16:51:29.525 [main] INFO  c.g.DemoApplication - [logStarted,59] - Started DemoApplication in 2.046 seconds (JVM running for 3.777)16:51:34.978 [http-nio-80-exec-1] INFO  o.a.c.c.C.[.[.[/] - [log,173] - Initializing Spring DispatcherServlet 'dispatcherServlet'[将当前数据源改为]:TEST01[获取当前数据源的类型为]:TEST0116:51:35.022 [http-nio-80-exec-1] INFO  c.z.h.HikariDataSource - [getConnection,110] - HikariPool-1 - Starting...16:51:35.102 [http-nio-80-exec-1] INFO  c.z.h.pool.PoolBase - [getAndSetNetworkTimeout,525] - HikariPool-1 - Driver does not support get/set network timeout for connections. (oracle.jdbc.driver.T4CConnection.getNetworkTimeout()I)16:51:35.106 [http-nio-80-exec-1] INFO  c.z.h.HikariDataSource - [getConnection,123] - HikariPool-1 - Start completed.[将当前数据源改为]:TEST021数据源当前用户数为:29[获取当前数据源的类型为]:TEST0216:51:35.192 [http-nio-80-exec-1] INFO  c.z.h.HikariDataSource - [getConnection,110] - HikariPool-2 - Starting...16:51:35.193 [http-nio-80-exec-1] WARN  c.z.h.u.DriverDataSource - [<init>,68] - Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.16:51:35.840 [http-nio-80-exec-1] INFO  c.z.h.HikariDataSource - [getConnection,123] - HikariPool-2 - Start completed.2数据源当前用户数为:23数据源当前用户数为:29[获取当前数据源的类型为]:TEST01

这是我的程序运行的结果。

第三种配置:DataSource类的代码换了换方式而已:

/** * 切换数据注解 可以用于类或者方法级别 方法级别优先级 > 类级别 */@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface DataSource {    String value() default "test01"; //该值即key值,默认使用默认数据库}

当然这个类的判断也要修改一下哦:DynamicDataSourceAspect

package com.gbicc.demo.config; import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component; @Aspect@Componentpublic class DynamicDataSourceAspect {    @Before("@annotation(dataSource)")//拦截我们的注解    public void changeDataSource(JoinPoint point, DataSource dataSource) throws Throwable {        String value = dataSource.value();        if (value.equals("test01")){            DataSourceType.setDataBaseType(DataBaseType.TEST01);        }else if (value.equals("test02")){            DataSourceType.setDataBaseType(DataBaseType.TEST02);        }else {            DataSourceType.setDataBaseType(DataBaseType.TEST01);//默认使用主数据库        }     }     @After("@annotation(dataSource)") //清除数据源的配置    public void restoreDataSource(JoinPoint point, DataSource dataSource) {        DataSourceType.clearDataBaseType();      }}

mybatis多数据源配置_springboot+mybatis+aop配置动态数据源相关推荐

  1. SpringBoot多数据源切换,AOP实现动态数据源切换

    SpringBoot多数据源切换,AOP实现动态数据源切换 操作数据一般都是在DAO层进行处理,可以选择直接使用JDBC进行编程 或者是使用多个DataSource 然后创建多个SessionFact ...

  2. mysql多数据源切换_Springboot项目实现Mysql多数据源切换的完整实例

    一.分析AbstractRoutingDataSource抽象类源码 关注import org.springframework.jdbc.datasource.lookup.AbstractRouti ...

  3. Spring AOP之四:利用AOP实现动态数据源切换

    2019独角兽企业重金招聘Python工程师标准>>> 简介和依赖 项目的前提是安装了MySQL数据库,并且建立了2个数据库一个是master,一个是slave,并且这2个数据库都有 ...

  4. 【原】继承AbstractRoutingDataSource再通过AOP实现动态数据源切换

    关于AbstractRoutingDataSource动态切换数据源是我在研究某开源项目时候才注意到的,大概就看懂了Spring AOP切面这里,根据作者的意思是通过继承这个抽象类可以实现数据源的动态 ...

  5. 所有配置_Springboot 打印所有配置

    对接一个第三方应用做调试时,想打印出所有的配置,调试我这边做的配置是否有效,摸索了一番后找到了一个解决方案,废话不多说,直接上代码. image.png package com.marioplus;i ...

  6. springboot quartz 动态配置_springboot集成quartz实现动态任务调度

    quartz是一个开源的作业调度框架,本文就是介绍下springboot框架下继承quartz的一些使用示例 首先我们需要添加quartz的spring-boot-starter-quartz依赖 o ...

  7. 手撸一个动态数据源的Starter 完整编写一个Starter及融合项目的过程 保姆级教程

    手撸一个动态数据源的Starter! 文章目录 手撸一个动态数据源的Starter! 前言 一.准备工作 1,演示 2,项目目录结构 3,POM文件 二.思路 三.编写代码 1,定义核心注解 Ds 2 ...

  8. Spring 下,关于动态数据源的事务问题的探讨

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:青石路 cnblogs.com/youzhibing ...

  9. springboot多数据源动态数据源(主从)

    多数据源 使用Spring Boot时,默认情况下,配置DataSource非常容易.Spring Boot会自动为我们配置好一个DataSource. 如果在application.yml中指定了s ...

  10. 分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离

    分布式数据层中间件: 1.简介: 分布式数据访问层中间件,旨在为供一个通用数据访问层服务,支持MySQL动态数据源.读写分离.分布式唯一主键生成器.分库分表.动态化配置等功能,并且支持从客户端角度对数 ...

最新文章

  1. 三、Oracle的简单查询
  2. 关于pipeline
  3. 有关gcc,make,gdb的知识
  4. Linux 下的进程间通信:管道、消息队列、共享文件、共享内存
  5. 989. 数组形式的整数加法
  6. [BZOJ4987] Tree
  7. c语言 机器语言 汇编语言_多语言机器人新闻记者
  8. Python人脸检测与人脸数据集的生成
  9. SQL alter操作
  10. 2022-2027年中国虾养殖行业市场调研及未来发展趋势预测报告
  11. cobar mysql_mysql分布式中间件cobar
  12. 5GC 会话建立流程
  13. 信息系统安全 总结提纲
  14. jquery实现注册表单验证
  15. 购物车的制作 与注册表单验证
  16. mongodb 分片集群安装 -- 二进制文件安装
  17. 计算机软件ae常用英语,AE英文插件该怎么翻译?
  18. 实战新浪微博、腾讯微博的分享功能
  19. 计算机中丟失Slc.dll,调试符号不会加载slc.dll和sppc.dll
  20. 李骐老师--实战项目管理专家--老师多个课程版权--沪师经纪刘建

热门文章

  1. 记录一次多表关联查询
  2. shell脚本中的逻辑判断、文件目录属性判断、if特殊用法、case判断
  3. 逆向微信-分析学习微信是如何快速构建静态TableView界面的
  4. SQL Server 2016 SP1 标准版等同企业版?!
  5. 安装了IE8.0之后网页按钮变小的恢复
  6. php结合nginx,mysql
  7. php+mysql+apache的安装方法
  8. 微信短信验证码注意事项(tp3.2-腾讯云)
  9. 04.electron-(使用remove模块及安全策略)
  10. sql防注入查询参数化parameters