一,为什么要访问多个mysql数据源?

实际的生产环境中,我们的数据并不会总放在一个数据库,

例如:业务数据库:存放了用户/商品/订单

统计数据库:按年、月、日的针对用户、商品、订单的统计表

因为统计库中的数据是对业务库中数据的提取和挖掘,

但与业务的运行没有直接关系,所以我们会分开存放,

把它们放到两个库中。

但有时我们会有访问两个库中数据的需求,这时就需要访问两个或以上数据源

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目地址:

https://github.com/liuhongdi/multimysql

2,项目原理

我们需要访问两个数据库,一个名字:store,

一个名字:tiku

然后在一个方法中获取到两个库中指定数据表的数据

3,项目结构,如图:

三,配置文件说明

1,application.properties

#mysql
spring.datasource.store.url=jdbc:mysql://127.0.0.1:3306/store?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.store.username=root
spring.datasource.store.password=lhddemo
spring.datasource.store.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.store.maximum-pool-size=12
spring.datasource.store.minimum-idle=10
spring.datasource.store.idle-timeout=500000
spring.datasource.store.max-lifetime=540000 spring.datasource.tiku.url=jdbc:mysql://localhost:3306/tiku?useUnicode=true&characterEncoding=utf-8&useSSL=FALSE&serverTimezone=Asia/Shanghai
spring.datasource.tiku.username=root
spring.datasource.tiku.password=lhddemo
spring.datasource.tiku.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.tiku.maximum-pool-size=12
spring.datasource.tiku.minimum-idle=10
spring.datasource.tiku.idle-timeout=500000
spring.datasource.tiku.max-lifetime=540000

说明:我们需要访问两个数据库:store,tiku

注意max-lifetime的设置:这个值是连接池中一个连接的生命时间长度,

设置应该低于mysql配置文件中的wait-timeout值的设置,

idle-timeout是指空闲的连接的超时时间,应该不大于max-lifetime的值

maximum-pool-size是池中连接的数据,默认值是10,我们设置为12,保留默认值也没问题

2,两个数据表的结构:

store.goods

CREATE TABLE `goods` (
`goodsId` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`goodsName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'name',
`subject` varchar(200) NOT NULL DEFAULT '' COMMENT '标题',
`price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
`stock` int(11) NOT NULL DEFAULT '0' COMMENT 'stock',
PRIMARY KEY (`goodsId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表'

tiku.category

CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`category_name` varchar(100) NOT NULL DEFAULT '' COMMENT '分类名称',
PRIMARY KEY (`category_id`),
UNIQUE KEY `category_name` (`category_name`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='分类'

四,java代码说明

1,StoreDataSourceConfig.java

@Configuration
//得到mapper
@MapperScan(basePackages = StoreDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "storeSqlSessionFactory")
public class StoreDataSourceConfig {
// 指定mapper 目录,与其他数据源隔离
static final String PACKAGE = "com.multimysql.demo.mapper.store";
static final String MAPPER_LOCATION = "classpath:mapper/store/*.xml"; @Value("${spring.datasource.store.url}")
private String url; @Value("${spring.datasource.store.username}")
private String username; @Value("${spring.datasource.store.password}")
private String password; @Value("${spring.datasource.store.driver-class-name}")
private String driverClass; @Value("${spring.datasource.store.maximum-pool-size}")
private int maximumPoolSize; @Value("${spring.datasource.store.minimum-idle}")
private int minimumIdle; @Value("${spring.datasource.store.idle-timeout}")
private long idleTimeout; @Value("${spring.datasource.store.max-lifetime}")
private long maxLifetime; //得到datasource
@Bean(name = "storeDataSource")
@Primary
public DataSource storeDataSource() {
HikariDataSource dataSource=new HikariDataSource();
dataSource.setJdbcUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClass);
dataSource.setMaximumPoolSize(maximumPoolSize);
dataSource.setMinimumIdle(minimumIdle);
dataSource.setIdleTimeout(idleTimeout);
dataSource.setMaxLifetime(maxLifetime);
return dataSource;
} //得到TransactionManager
@Bean(name = "storeTransactionManager")
@Primary
public DataSourceTransactionManager storeTransactionManager() {
return new DataSourceTransactionManager(storeDataSource());
} //得到SqlSessionFactory
@Bean(name = "storeSqlSessionFactory")
@Primary
public SqlSessionFactory storeSqlSessionFactory(@Qualifier("storeDataSource") DataSource storeDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(storeDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(StoreDataSourceConfig.MAPPER_LOCATION));
return sessionFactory.getObject();
}
}

生成到store数据库的数据源,

注意指定了mapper文件的路径,

两个不同数据源的mapper分别放到了不同的目录下,避免有冲突

2,TikuDataSourceConfig.java,

为节省篇幅,不再贴出代码,大家可以在github上自取

3,HomeController.java

@Controller
@RequestMapping("/home")
public class HomeController { @Resource
private GoodsMapper goodsMapper; @Resource
private CategoryMapper categoryMapper; @Resource
private HikariDataSource storeDataSource; @Resource
private HikariDataSource tikuDataSource; //商品详情 参数:商品id
@GetMapping("/goodsone")
@ResponseBody
public String goodsOne(@RequestParam(value="goodsid",required = true,defaultValue = "0") Long goodsId) throws SQLException {
System.out.println("------goodsInfo begin");
Goods goods = goodsMapper.selectOneGoods(goodsId);
Category category=categoryMapper.selectOneCategory("4");
return "goods:"+goods.toString()+";category:"+category.toString();
} //显示统计信息
@GetMapping("/stats")
@ResponseBody
public Object stats() throws SQLException { Connection connection = storeDataSource.getConnection();
connection.close();
HikariPoolMXBean storePool = storeDataSource.getHikariPoolMXBean();
int active = storePool.getActiveConnections();
int total = storePool.getTotalConnections();
int idle = storePool.getIdleConnections();
int theadsAwaitting = storePool.getThreadsAwaitingConnection();
int maximumPoolsize = storeDataSource.getMaximumPoolSize();
int minimumIdle = storeDataSource.getMinimumIdle();
String poolName = storeDataSource.getPoolName();
long connTimeout = storeDataSource.getConnectionTimeout();
long idleTimeout = storeDataSource.getIdleTimeout();
long maxLifetime = storeDataSource.getMaxLifetime(); String status = "store pool:<br/>";
status += "poolName:" + poolName+"<br/>";
status += "active:" + active+"<br/>";
status += "total:" + total+"<br/>";
status += "idle:" + idle+"<br/>";
status += "theadsAwaitting:" + theadsAwaitting+"<br/>";
status += "maximumPoolsize:" + maximumPoolsize+"<br/>";
status += "minimumIdle:" + minimumIdle+"<br/>";
status += "connTimeout:" + connTimeout+"<br/>";
status += "idleTimeout:" + idleTimeout+"<br/>";
status += "maxLifetime:" + maxLifetime+"<br/>"; Connection tikuConnection = tikuDataSource.getConnection();
tikuConnection.close();
HikariPoolMXBean tikuPool = tikuDataSource.getHikariPoolMXBean();
int active2 = tikuPool.getActiveConnections();
int total2 = tikuPool.getTotalConnections();
int idle2 = tikuPool.getIdleConnections();
int theadsAwaitting2 = tikuPool.getThreadsAwaitingConnection();
int maximumPoolsize2 = tikuDataSource.getMaximumPoolSize();
int minimumIdle2 = tikuDataSource.getMinimumIdle();
String poolName2 = tikuDataSource.getPoolName();
long connTimeout2 = tikuDataSource.getConnectionTimeout();
long idleTimeout2 = tikuDataSource.getIdleTimeout();
long maxLifetime2 = tikuDataSource.getMaxLifetime(); status += "tiku pool:<br/>";
status += "poolName:" + poolName2+"<br/>";
status += "active:" + active2+"<br/>";
status += "total:" + total2+"<br/>";
status += "idle:" + idle2+"<br/>";
status += "theadsAwaitting:" + theadsAwaitting2+"<br/>";
status += "maximumPoolsize:" + maximumPoolsize2+"<br/>";
status += "minimumIdle:" + minimumIdle2+"<br/>";
status += "connTimeout:" + connTimeout2+"<br/>";
status += "idleTimeout:" + idleTimeout2+"<br/>";
status += "maxLifetime:" + maxLifetime2+"<br/>"; return status;
}

说明:goodsOne方法:返回store.goods表中的商品信息和tiku.category表中的分类信息

stats方法:打印两个Hikari连接池的信息

4,其他的 类文件和mapper文件,请访问github获取

五,效果测试

1,访问商品信息地址:

http://127.0.0.1:8080/home/goodsone?goodsid=3

返回:

goods: Goods:goodsId=3 goodsName=100分电动牙刷 subject=好用到让你爱上刷牙 price=59.00 stock=15
category: Goods:category_id=4 category_name=bash

2,访问统计地址:

http://127.0.0.1:8080/home/stats

返回:

store pool:
poolName:HikariPool-1
active:0
total:10
idle:10
theadsAwaitting:0
maximumPoolsize:12
minimumIdle:10
connTimeout:30000
idleTimeout:500000
maxLifetime:540000

tiku pool:
poolName:HikariPool-2
active:0
total:10
idle:10
theadsAwaitting:0
maximumPoolsize:12
minimumIdle:10
connTimeout:30000
idleTimeout:500000
maxLifetime:540000

六,查看spring boot的版本

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.1.RELEASE)

spring boot:使用mybatis访问多个mysql数据源/查看Hikari连接池的统计信息(spring boot 2.3.1)的更多相关文章

  1. spring boot:使mybatis访问多个druid数据源(spring boot 2.3.2)

    一,为什么要使用多个数据源? 1,什么情况下需要使用多个数据源? 当我们需要访问不同的数据库时,则需要配置配置多个数据源, 例如:电商的业务数据库(包括用户/商品/订单等)            和统 ...

  2. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-1.整合Mybatis访问数据库和阿里巴巴数据源

    笔记 1.整合Mybatis访问数据库和阿里巴巴数据源     简介:整合mysql 加入mybatis依赖,和加入alibaba druid数据源 1.加入依赖(可以用 http://start.s ...

  3. DB数据源之SpringBoot+MyBatis踏坑过程(五)手动使用Hikari连接池

    DB数据源之SpringBoot+MyBatis踏坑过程(五)手动使用Hikari连接池 liuyuhang原创,未经允许禁止转载  系列目录连接 DB数据源之SpringBoot+Mybatis踏坑 ...

  4. Druid连接池及监控在spring中的配置

    Druid连接池及监控在spring配置如下: <bean id="dataSource" class="com.alibaba.druid.pool.DruidD ...

  5. Spring学习总结(12)——Druid连接池及监控在spring配置

    Druid连接池及监控在spring配置如下: <bean id="dataSource" class="com.alibaba.druid.pool.DruidD ...

  6. C3P0连接池在hibernate和spring中的配置

    首先为什么要使用连接池及为什么要选择C3P0连接池,这里就不多说了,目前C3P0连接池还是比较方便.比较稳定的连接池,能与spring.hibernate等开源框架进行整合. 一.hibernate中 ...

  7. Spring boot教程mybatis访问MySQL的尝试

    Windows 10家庭中文版,Eclipse,Java 1.8,spring boot 2.1.0,mybatis-spring-boot-starter 1.3.2,com.github.page ...

  8. 使用MyBatis集成阿里巴巴druid连接池(不使用spring)

    在工作中发现mybatis默认的连接池POOLED,运行时间长了会报莫名其妙的连接失败错误.因此采用阿里巴巴的Druid数据源(码云链接 ,中文文档链接). mybatis更多数据源参考博客链接 . ...

  9. SpringBoot配置MySql数据库和Druid连接池

    1.pom文件增加相关依赖 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connec ...

随机推荐

  1. 如何在不使用OleDbCommandBuilder情况下使用OleDbDataAdapter更新Access数据库记录

    我在博客园的博问和微软论坛都曾经请教了这个问题(问题链接),可能我的问题太简单,并没有获得太多解答. 到今天为止,我自己通过查找和摸索,基本把这个问题解决了,还是记录下来,供其他朋友参考. 第一次解决 ...

  2. 【NOIP2013模拟】七夕祭

    题目描述七夕节因牛郎织女的传说而被扣上了「情人节」的帽子.于是TYVJ今年举办了一次线下七夕祭.Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩. TYVJ七夕祭和 ...

  3. openstack (共享服务) 消息队列rabbitmq服务

    云计算openstack共享组件——消息队列rabbitmq(3)   一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队 ...

  4. PostGreSQL不同索引类型(btree & hash)的性能问题

    在关系型数据库调优中,查询语句涉及到的索引类型是不得不考虑的一个问题.不同的类型的索引可能会适用不同类型的业务场景.这里我们所说的索引类型指的是访问方法(Access Method),至于从其他维度区 ...

  5. 记一次由selinux引起的使用cat查看文件报错Permission denied的问题排查

    事件起因:如下 1.在服务器上root用户,定期会生成一个文件,到/tmp目录,如:qq_5201351.txt,给other加上了r读取 2.zabbix端会周期性取这台服务器/tmp/qq_520 ...

  6. 面试官:讲讲Redis的五大数据类型?如何使用?(内含完整测试源码)

    写在前面 最近面试跳槽的小伙伴有点多,给我反馈的面试情况更是千差万别,不过很多小伙伴反馈说:面试中的大部分问题都能够在我的公众号[冰河技术]中找到答案,面试过程还是挺轻松的,最终也是轻松的拿到了Off ...

  7. burp suite 之 Scanner(漏洞扫描)

    Scanner选项:是一个进行自动发现 web 应用程序的安全漏洞的工具. 将抓取的包 通过选项卡发送至 Scanner下的Scan queue 首先来介绍 Scanner 下的 lssue acti ...

  8. 关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。

    近来对 amigo 开发期间的遇到 I2C 问题做一下总结. 我们发现有一些 I2C 设备搜索不到,主要原因是 DATA 的信号衰减,也可能是 I2C 的总线被拉住了. 软件层面的问题 例如在实现 A ...

  9. Layman H5+Webapp+MUI App 页面滑至到底部自动加载新的内容

    要点:使用jquery的scroll()方法实现,当用户滚动指定的元素时,会发生 scroll 事件 scroll 事件适用于所有可滚动的元素和 window 对象(浏览器窗口) scroll() 方 ...

  10. C++中cout和cerr

    参考:https://blog.csdn.net/garfield2005/article/details/7639833 之前一直在用,但就是没在意两者到底有啥却别,今天又想到这个问题,总结下吧(以 ...