springboot2 + mybatis 多种方式实现多数据配置
业务系统复杂程度增加,为了解决数据库I/O瓶颈,很自然会进行拆库拆表分服务来应对。这就会出现一个系统中可能会访问多处数据库,需要配置多个数据源。
第一种场景:项目服务从其它多处数据库取基础数据进行业务处理,因此各库之间不会出现重表等情况。
第二种场景:为了减轻写入压力进行读写分库,读走从库,写为主库。此种表名等信息皆为一致。
第三种场景:以上两种皆有。对于某些业务需要大数据量的汇总统计,希望不影响正常业务必须走从库(表信息一致),某些配置信息不存在读写压力,出现不分库(表信息不一致)
项目源代码:
https://github.com/zzsong/springboot-multiple-datasource.git
有三个目录:
one:
直接使用多@Bean配置,@MapperScan来路径区分读何库 two:
使用注解的方式来标识走何dataSource,AOP拦截注入动态数据源 third:
使用spring的Bean命名策略进行区分数据来源
项目技术选型: springBoot2.2.5 + mybatis + druid + mysql
先看主要的pom包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
application.yml
spring:
datasource:
druid:
core:
url: jdbc:mysql:///kc_core?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
schedule:
url: jdbc:mysql:///kc_schedule?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mysql新版本必须带有serverTimezone,不然会报连接异常。
第一种:通过@MapperScans 扫描匹配相关的数据源
@Configuration
@MapperScans({
@MapperScan(basePackages = "com.zss.one.mapper.core", sqlSessionTemplateRef = "coreSqlSessionTemplate",sqlSessionFactoryRef = "coreSqlSessionFactory"),
@MapperScan(basePackages = "com.zss.one.mapper.schedule", sqlSessionTemplateRef = "scheduleSqlSessionTemplate",sqlSessionFactoryRef = "scheduleSqlSessionFactory")
})
public class MybatisOneConfig { @Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.core")
public DataSource coreDataSource(){
return DruidDataSourceBuilder.create().build();
} @Bean
public SqlSessionFactory coreSqlSessionFactory(@Qualifier("coreDataSource") DataSource coreDataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(coreDataSource);
sessionFactory.getObject().getConfiguration().setJdbcTypeForNull(null);
sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return sessionFactory.getObject();
} @Bean
public SqlSessionTemplate coreSqlSessionTemplate(@Qualifier("coreSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
} //======schedule========
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.schedule")
public DataSource scheduleDataSource(){
return DruidDataSourceBuilder.create().build();
} @Bean
public SqlSessionFactory scheduleSqlSessionFactory(@Qualifier("scheduleDataSource") DataSource coreDataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(coreDataSource);
sessionFactory.getObject().getConfiguration().setJdbcTypeForNull(null);
sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return sessionFactory.getObject();
} @Bean
public SqlSessionTemplate scheduleSqlSessionTemplate(@Qualifier("scheduleSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
第二种是动态数据源模式,通过AOP切入注解引导使用何数据源。用自定义注解@interface来标识方法走对应的数据源。
注意事项:类中的方法再调用带数据源的方法,不能被AOP切入
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
String value();
}
extends spring的动态DataSource路由来匹配
public class DynamicDataSource extends AbstractRoutingDataSource { @Override
protected Object determineCurrentLookupKey() {
return DataSourceContextRouting.getDataSourceName();
}
}
@Configuration
//@EnableConfigurationProperties(MybatisProperties.class)//不要使用此公共配置,Configuration会破坏相关dataSource的配置
@MapperScan("com.zss.two.mapper")
public class MybatisConfig { @Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.core")
public DataSource coreDataSource() {
return DruidDataSourceBuilder.create().build();
} @Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.schedule")
public DataSource scheduleDataSource() {
return DruidDataSourceBuilder.create().build();
} @Autowired
@Qualifier("coreDataSource")
private DataSource coreDataSource; @Autowired
@Qualifier("scheduleDataSource")
private DataSource scheduleDataSource; @Bean
public DynamicDataSource dataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceConstants.CORE_DATA_SOURCE, coreDataSource);
targetDataSources.put(DataSourceConstants.SCHEDULE_DATA_SOURCE, scheduleDataSource); DynamicDataSource dataSource = new DynamicDataSource(); //设置数据源映射
dataSource.setTargetDataSources(targetDataSources);
//// 设置默认数据源,当无法映射到数据源时会使用默认数据源
dataSource.setDefaultTargetDataSource(coreDataSource);
dataSource.afterPropertiesSet();
return dataSource;
}
/**
* 根据数据源创建SqlSessionFactory
*/
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.getObject().getConfiguration().setJdbcTypeForNull(null);
sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return sessionFactory.getObject();
} @Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
第三种,自定义Bean命名策略,按beanName进行自动匹配使用数据源
@Component
public class CoreBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return "core"+ ClassUtils.getShortName(definition.getBeanClassName());
}
} @Component
public class ScheduleBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return "schedule"+ ClassUtils.getShortName(definition.getBeanClassName());
}
}
使用mybatis MapperScannerConfigurer自动扫描,将Mapper接口生成注入到spring
@Bean
public MapperScannerConfigurer coreMapperScannerConfig(CoreBeanNameGenerator coreBeanNameGenerator){
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setNameGenerator(coreBeanNameGenerator);
configurer.setBasePackage("com.zss.third.mapper.core,com.zss.third.mapper.order");
configurer.setSqlSessionFactoryBeanName("coreSqlSessionFactory");
configurer.setSqlSessionTemplateBeanName("coreSqlSessionTemplate");
return configurer;
} @Bean
public MapperScannerConfigurer scheduleMapperScannerConfig(ScheduleBeanNameGenerator scheduleBeanNameGenerator){
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setNameGenerator(scheduleBeanNameGenerator);
configurer.setBasePackage("com.zss.third.mapper.schedule,com.zss.third.mapper.order");
configurer.setSqlSessionFactoryBeanName("scheduleSqlSessionFactory");
configurer.setSqlSessionTemplateBeanName("scheduleSqlSessionTemplate");
return configurer;
}
到此,三种多数据源匹配主要点介绍完,详细直接下载github项目。 在resources/db含有相关测试表及数据脚本。
springboot2 + mybatis 多种方式实现多数据配置的更多相关文章
- Spring实现Ioc的多种方式--控制反转、依赖注入、xml配置的方式实现IoC、对象作用域
Spring实现Ioc的多种方式 一.IoC基础 1.1.概念: 1.IoC 控制反转(Inversion of Control) IoC是一种设计思想. 2.DI 依赖注入 依赖注入是实现IoC的一 ...
- Django 缓存配置的多种方式
django 的缓存配置有多种方式,主要包含以下几种: 1.开发调试模式 2.内存模式 3.使用文件 4.直接使用数据库 5.使用redis或者memcache 这里主要是记录一下那些不常用,但是在微 ...
- Spring Boot 入门系列(二十三)整合Mybatis,实现多数据源配置!
d之前介绍了Spring Boot 整合mybatis 使用注解方式配置的方式实现增删改查以及一些复杂自定义的sql 语句 .想必大家对spring boot 项目中,如何使用mybatis 有了一定 ...
- idea打包jar的多种方式
这里总结出用IDEA打包jar包的多种方式,以后的项目打包Jar包可以参考如下形式: 用IDEA自带的打包形式 用Maven插件maven-shade-plugin打包 用Maven插件maven-a ...
- MySQL JDBC/MyBatis Stream方式读取SELECT超大结果集
情景: 遍历并处理一个大表中的所有数据, 这个表中的数据可能会是千万条或者上亿条, 很多人可能会说用分页limit……但需求本身一次性遍历更加方便, 且Oracle/DB2都有方便的游标机制. 对DB ...
- Spring学习总结(一)——Spring实现IoC的多种方式
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法.没有IoC的程序中我们使用面向对象编程对象的创 ...
- java 获取classpath下文件多种方式
java 获取classpath下文件多种方式 一:properties下配置 在resources下定义server.properties register.jks.path=classpath\: ...
- myBatis 基础测试 表关联关系配置 集合 测试
myBatis 基础测试 表关联关系配置 集合 测试 测试myelipse项目源码 sql 下载 http://download.csdn.net/detail/liangrui1988/599388 ...
- Spring实现IoC的多种方式
目录 一.使用XML配置的方式实现IOC 二.使用Spring注解配置IOC 三.自动装配 四.零配置实现IOC 五.示例下载 控制反转IoC(Inversion of Control),是一种设计思 ...
随机推荐
- 从赴美IPO绝迹 看那些烧成泡沫的互联网企业
曾经,赴美上市是很多中国企业的终极梦想.然而在当下,随着中概股在美国股市股价的不断走低.中国赴美上市企业私有化速度的加快,大众才发现,原来美国股市并不是那么好混的.但不管怎样,赴美上市始终是一种荣耀. ...
- 模拟HTTP请求超时时间设置
HTTP请求有两个超时时间:一个是连接超时时间,另一个是数据传输的最大允许时间(请求资源超时时间). 使用curl命令行 连接超时时间用 --connect-timeout 参数来指定 数据传输的最大 ...
- 安卓权威编程指南-笔记(第24章 Looper Handler 和 HandlerThread)
AsyncTask是执行后台线程的最简单方式,但它不适用于那些重复且长时间运行的任务. 1. Looper Android中,线程拥有一个消息队列(message queue),使用消息队列的线程叫做 ...
- Flutter调研(1)-Flutter基础知识
工作需要,因客户端有部分页面要使用flutter编写,需要QA了解一下flutter相关知识,因此,做了flutter调研,包含安装,基础知识与demo编写,第二部分是安装与环境配置. —— Flut ...
- 机器学习基础——简单易懂的K邻近算法,根据邻居“找自己”
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天的文章给大家分享机器学习领域非常简单的模型--KNN,也就是K Nearest Neighbours算法,翻译过来很简单,就是K最近邻居 ...
- vue 打包体积过大 实现懒加载 ????
import Vue from ‘vue’ import Router from 'vue-router' //把路由对应的组件定义成异步组纪检 const hello = resolve => ...
- ElementUI el-table 在flex下的宽度自适应问题
BUG:在flex容器下面的一个flex:1的子容器里面写了个el-table用来展示列表数据,在做宽度自适应测试的时候发现该组件的宽度只会增加不会缩小. Debug:通过控制台发现组件生成的tabl ...
- 转pdf
一.转印厂pdf(书本类及折页类) 1.储存为(Ctrl+Shift+S) 2.保存类型选择 pdf 3.常规==>Adobe PDF预设==>选择印刷质量 4.选择标记和出血==&g ...
- 【vue】---- v-model在自定义组件中的使用
1. v-model简介 可以用 v-model 指令在表单 <input>.<textarea> 及 <select> 元素上创建双向数据绑定,它的本质是一个语法 ...
- js函数的三种成创建方式以及它们各自的不同
js有三种创建函数的方式: 1.function语句(也叫函数声明) function sum(a, b) { return a + b; } sum(1, 2); // 3 2. 函数直接量,又叫函 ...