通过springboot+mybatis+druid配置动态数据源
作者:夜月河色 发布时间:2023-06-20 16:48:30
标签:springboot,mybatis,druid,动态,数据源
一、建数据库和表
1.数据库demo1放一张user表
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'aa');
INSERT INTO `user` VALUES ('2', 'bb');
2.数据库demo2放一张role表
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'CC');
INSERT INTO `role` VALUES ('2', 'DD');
二、pom.xml引入包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- alibaba druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- dynamic-->
<dependency>
<groupId>com.typesafe.dynamicdatasource</groupId>
<artifactId>dynamic-data-source_2.11</artifactId>
</dependency>
三、用generator插件生成user、role两张表的实体类、mapper.java、mapper.xml
User.java
Role.java
UserMapper.java
RoleMapper.java
UserMapper.xml
RoleMapper.xml
四、配置application.yml
server:
port: 8088
mybatis:
mapper-locations: classpath:mapper/*.xml
spring:
datasource:
db1:
url: jdbc:mysql://localhost:3306/demo1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
#驱动包
driver-class-name: com.mysql.cj.jdbc.Driver
#初始连接数
initial-size: 5
#最小空闲数
min-idle: 5
#最大活动数
max-active: 20
#等待超时时间
max-wait: 60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 300000
#验证数据库连接的查询语句,MYSQL是select 1
validation-query: SELECT 1 FROM DUAL
#空闲时测试,testOnBorrow和testOnReturn在生产环境一般是不开启的,主要是性能考虑。失效连接主要通过testWhileIdle保证
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个链接上的PSCache大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
#配置监控统计拦截的filters,去掉后监控界面sql无法统计,‘wall'用于防火墙,此处是filter修改的地方
filters: stat,wall
#通过connectproperties属性来打开mergesql功能:慢sql记录
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#合并多个DruidDataSource
useGlobalDataSourceStat: true
db2:
url: jdbc:mysql://localhost:3306/demo2?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
#驱动包
driver-class-name: com.mysql.cj.jdbc.Driver
#初始连接数
initial-size: 5
#最小空闲数
min-idle: 5
#最大活动数
max-active: 20
#等待超时时间
max-wait: 60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 300000
#验证数据库连接的查询语句,MYSQL是select 1
validation-query: SELECT 1 FROM DUAL
#空闲时测试,testOnBorrow和testOnReturn在生产环境一般是不开启的,主要是性能考虑。失效连接主要通过testWhileIdle保证
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个链接上的PSCache大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
#配置监控统计拦截的filters,去掉后监控界面sql无法统计,‘wall'用于防火墙,此处是filter修改的地方
filters: stat,wall
#通过connectproperties属性来打开mergesql功能:慢sql记录
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#合并多个DruidDataSource
useGlobalDataSourceStat: true
五、启动类扫描mapper.java文件
@SpringBootApplication
@MapperScan("com.example.demo.dao")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
六、定义DataSourceConfig, 将application.yml中的配置导入DataSource中,并注入到bean
@Configuration
public class DataSourceConfig {
//从配置文件配置数据源
@Primary
@Bean(name="datasource1")
@ConfigurationProperties("spring.datasource.db1")
public DataSource dataSource1(){
return new DruidDataSource();
}
//从配置文件配置数据源
@Bean(name="datasource2")
@ConfigurationProperties("spring.datasource.db2")
public DataSource dataSource2(){
return new DruidDataSource();
}
//动态数据源 进行数据源切换
@Bean(name="dynamicDataSource")
public DataSource dynamicDataSource(){
DynamicDataSource dynamicDatasource=new DynamicDataSource();
//设置默认数据源
dynamicDatasource.setDefaultTargetDataSource(dataSource1());
//配置多数据源
Map<Object,Object> dsMap=new HashMap<>();
dsMap.put("datasource1",dataSource1());
dsMap.put("datasource2",dataSource2());
//将多数据源放到数据源池中
dynamicDatasource.setTargetDataSources(dsMap);
return dynamicDatasource;
}
}
七、定义动态数据源切换类DynamicDataSourceContextHolder
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<String> contextHolder=new ThreadLocal<>();
//设置数据源名称
public static void setDB(String dbType){
contextHolder.set(dbType);
}
//获取数据源名称
public static String getDB(){
return contextHolder.get();
}
//清除数据源名
public static void clearDB(){
contextHolder.remove();
}
}
八、定义获取动态数据源类DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDB();
}
}
九、定义mybatis配置类,将DynamicDataSource放入SqlSessionFactoryBean中
@EnableTransactionManagement
@Configuration
public class MyBatisConfig {
@Resource(name = "dynamicDataSource")
private DataSource dynamicDataSource;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource);//将动态数据源bean配置到sqlsessionfactory
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new DataSourceTransactionManager(dynamicDataSource);
}
}
十、定义用于切换数据源的注解TargetDataSource
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
String value() default "datasource1";
}
十一、定义切面DynamicDataSourceAspect,用于拦截注解,并执行数据源切换功能
@Aspect
@Component
public class DynamicDataSourceAspect {
@Before("@annotation(targetDataSource)")
public void beforeSwitchDS(JoinPoint point,TargetDataSource targetDataSource){
DynamicDataSourceContextHolder.setDB(targetDataSource.value());
}
@After("@annotation(targetDataSource)")
public void afterSwitchDS(JoinPoint point,TargetDataSource targetDataSource){
DynamicDataSourceContextHolder.clearDB();
}
}
十二、测试类Test
@RestController
public class Test {
@Autowired
private RoleMapper roleMapper;
@Autowired
private UserMapper userMapper;
//未使用TargetDataSource注解,则使用默认数据源,即datasource1
@RequestMapping("/ds1")
public String selectDataSource1(){
return userMapper.selectByPrimaryKey(1).toString();
}
//使用了注解,则数据源为注解中指定的datasource2
@RequestMapping("/ds2")
@TargetDataSource("datasource2")
public String selectDataSource2(){
return roleMapper.selectByPrimaryKey(1).toString();
}
}
测试
1.输入
http://localhost:8088/ds1
返回
↓
2.输入
http://localhost:8088/ds2
返回
↓
结论:两次请求分别从不同的数据库获取到了数据,多数据源配置成功!
来源:https://www.jianshu.com/p/c09ef7e0c537


猜你喜欢
- 前言首先,事务这个概念是数据库层面的,Spring只是基于数据库中的事务进行扩展,以及提供了一些能让程序员更新方便操作事务的方式Spring
- 目录1、this代表了()的对象引用,super表示的是当前对象的()对象?2、输出内容是:3、下面程序的输出是:()4、执行下列代码的输出
- 引言相信大家在生活中,特别是最近的双十一活动期间,会收到很多短信,而那些短信都有两个特征,第一个是几乎都是垃圾短信,这个特点此处可以忽略不计
- 前言Java线程池中提交任务运行,通常使用execute()方法就足够了。那如果想要实现在主线程中阻塞获取线程池任务运行的结果,该怎么办呢?
- 一个popwindow,在弹出的时候背景是原界面的截图加高斯模糊效果:先给出popwindow的布局文件<?xml version=&
- 实现Android 滑动退出Activity的功能android向右滑动,退出activity//右滑删除 compile &
- 自动去除图像扫描黑边/// <summary>  
- 简单的说下实现来电秀的大概原理流程:首先通过监听来电状态,通过拦截来电然后在窗口弹出一层系统级别的弹窗,这层弹窗即是来电秀。先来两张效果图:
- 本文实例讲述了C#实现解压GZip文件的方法。分享给大家供大家参考。具体实现方法如下:public void ungzip(string p
- 问题今天在springboot中使用mybatis的时候不能字段不能够进行自动映射,mybatis的版本是3.5.11,数据库是按照下划线进
- 菜单是用户界面中最常见的元素之一,使用非常频繁,在Android中,菜单被分为如下三种,选项菜单(OptionsMenu)、上下文菜单(Co
- 本文以实例讲述了C#简单的向量用法,主要包括重载运算符>:以向量长度判断是否为真、重载运算符!=、<、<=等,具体实现代码
- package com.cjonline.foundation.evisa;import java.io.BufferedReader;im
- 本文实例讲述了Java判断两个日期相差天数的方法。分享给大家供大家参考。具体如下:import java.util.Calendar;pub
- checkpoint 机制的具体实现我们都知道为了优化分布式存储系统中 NameNode 的重启性能,我们引进了 checkpoint 机制
- 前言大家都知道类的继承规则:1、派生类自动包含基类的所有成员。但对于基类的私有成员,派生类虽然继承了,但是不能在派生类中访问。2、所有的类都
- tomcat内存溢出设置JAVA_OPTS答案1设置Tomcat启动的初始内存其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xm
- Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重
- 下面给大家介绍几种比较常见的解决办法,具体内容如下:1.有时候eclipse不自动编译,把project clean一下,让R.java重新
- 本文实例讲述了DevExpress设置饼状图的Lable位置的方法。分享给大家供大家参考。具体实现方法如下:关键代码如下:/// <s