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),是一种设计思 ...
随机推荐
- 算法小练#1 - Dany Yang
开始记录每周做过的算法题,这是第一周,新的开始 1021. 删除最外层的括号 题目要求如下: 有效括号字符串为空 ("")."(" + A + ")& ...
- Linux USB 鼠标驱动程序详解(转)
Linux USB 鼠标驱动程序详解 USB 总线引出两个重要的链表!一个 USB 总线引出两个重要的链表,一个为 USB 设备链表,一个为 USB 驱动链表.设备链表包含各种系统中的 USB 设备以 ...
- Python——4Dict和Set类型
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 如何正确使用redis分布式锁
前言 笔者在公司担任技术面试官,在笔者面试过程中,如果面试候选人提到了reids分布式锁,笔者都会问一下redis分布式锁的知识点,但是令笔者遗憾的是,该知识点十个人中有九个人都答得不清楚,或者回 ...
- Go-数据类型以及变量,常量,函数,包的使用
Go-数据类型以及变量,常量,函数,包的使用 一.数据类型 1.字符串类型 string -双引号包裹的:"xxx" -反引号包裹,可以换行, 注意: 区别于python,是没有单 ...
- 浅谈ConcurrentDictionary与Dictionary
在.NET4.0之前,如果我们需要在多线程环境下使用Dictionary类,除了自己实现线程同步来保证线程安全外,我们没有其他选择.很多开发人员肯定都实现过类似的线程安全方案,可能是通过创建全新的线程 ...
- htmlhint 规则详解
HTML 静态检查规则 HTMLHint 工具内置 23 条规则,可以对 HTML 代码文件进行静态代码检查,从而提高 HTML 代码编写的规范和质量.现在把 23 条规则翻译如下. 一.规则列表 标 ...
- Python -Selenium的安装和调用
安装selenium步骤: 1.安装pip(cmd命令行管理员方式): pip install pip 也可直接搜索pip,到官网下载安装 2.安装selenium(cmd命令行管理员方式): pip ...
- Docker部署LAMP项目
前言 之前我们学习了如何在Linux部署LAMP项目,今天我们来学习一下如何在Docker下部署LAMP项项目吧! Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条 ...
- git删除远程仓库中的文件夹
具体操作如下: git rm -r --cached .history #删除目录 git commit -m”删除.history文件夹” git push -r表示递归所有子目录,如果你要删 ...