mybatis多数据源配置_springboot+mybatis+aop配置动态数据源
废话不多说直接上代码
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配置动态数据源相关推荐
- SpringBoot多数据源切换,AOP实现动态数据源切换
SpringBoot多数据源切换,AOP实现动态数据源切换 操作数据一般都是在DAO层进行处理,可以选择直接使用JDBC进行编程 或者是使用多个DataSource 然后创建多个SessionFact ...
- mysql多数据源切换_Springboot项目实现Mysql多数据源切换的完整实例
一.分析AbstractRoutingDataSource抽象类源码 关注import org.springframework.jdbc.datasource.lookup.AbstractRouti ...
- Spring AOP之四:利用AOP实现动态数据源切换
2019独角兽企业重金招聘Python工程师标准>>> 简介和依赖 项目的前提是安装了MySQL数据库,并且建立了2个数据库一个是master,一个是slave,并且这2个数据库都有 ...
- 【原】继承AbstractRoutingDataSource再通过AOP实现动态数据源切换
关于AbstractRoutingDataSource动态切换数据源是我在研究某开源项目时候才注意到的,大概就看懂了Spring AOP切面这里,根据作者的意思是通过继承这个抽象类可以实现数据源的动态 ...
- 所有配置_Springboot 打印所有配置
对接一个第三方应用做调试时,想打印出所有的配置,调试我这边做的配置是否有效,摸索了一番后找到了一个解决方案,废话不多说,直接上代码. image.png package com.marioplus;i ...
- springboot quartz 动态配置_springboot集成quartz实现动态任务调度
quartz是一个开源的作业调度框架,本文就是介绍下springboot框架下继承quartz的一些使用示例 首先我们需要添加quartz的spring-boot-starter-quartz依赖 o ...
- 手撸一个动态数据源的Starter 完整编写一个Starter及融合项目的过程 保姆级教程
手撸一个动态数据源的Starter! 文章目录 手撸一个动态数据源的Starter! 前言 一.准备工作 1,演示 2,项目目录结构 3,POM文件 二.思路 三.编写代码 1,定义核心注解 Ds 2 ...
- Spring 下,关于动态数据源的事务问题的探讨
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:青石路 cnblogs.com/youzhibing ...
- springboot多数据源动态数据源(主从)
多数据源 使用Spring Boot时,默认情况下,配置DataSource非常容易.Spring Boot会自动为我们配置好一个DataSource. 如果在application.yml中指定了s ...
- 分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离
分布式数据层中间件: 1.简介: 分布式数据访问层中间件,旨在为供一个通用数据访问层服务,支持MySQL动态数据源.读写分离.分布式唯一主键生成器.分库分表.动态化配置等功能,并且支持从客户端角度对数 ...
最新文章
- 三、Oracle的简单查询
- 关于pipeline
- 有关gcc,make,gdb的知识
- Linux 下的进程间通信:管道、消息队列、共享文件、共享内存
- 989. 数组形式的整数加法
- [BZOJ4987] Tree
- c语言 机器语言 汇编语言_多语言机器人新闻记者
- Python人脸检测与人脸数据集的生成
- SQL alter操作
- 2022-2027年中国虾养殖行业市场调研及未来发展趋势预测报告
- cobar mysql_mysql分布式中间件cobar
- 5GC 会话建立流程
- 信息系统安全 总结提纲
- jquery实现注册表单验证
- 购物车的制作 与注册表单验证
- mongodb 分片集群安装 -- 二进制文件安装
- 计算机软件ae常用英语,AE英文插件该怎么翻译?
- 实战新浪微博、腾讯微博的分享功能
- 计算机中丟失Slc.dll,调试符号不会加载slc.dll和sppc.dll
- 李骐老师--实战项目管理专家--老师多个课程版权--沪师经纪刘建