Spring配置多数据库(采用数据连接池管理)

一,前言

大家在开发过程中,如果项目大一点就会遇到一种情况,同一个项目中可能会用到很多个数据源,那么这篇文章,博主为大家分享在spring应用中如何采用数据库连接池的方式配置配置多数据源。

本篇文章采用大家用的最多也是最受欢迎的HikariCP进行示范。

二,数据库连接池

数据库连接池是一个管理数据库连接的工具,它允许应用程序通过连接池来获取数据库连接,而不是每次需要时都重新创建连接。连接池通过维护一组预先创建好的数据库连接,以及管理连接的分配和释放,可以提高应用程序对数据库的访问性能和效率。

我们可以利用数据库连接池取实现连接的细节化配置。如最大连接数,最大空闲时间,最大连接等待时间等,这些方便了我们操作数据库,更可以有效避免过长等待导致程序卡死的情况。

常见的数据库连接池包括 HikariCP、Tomcat JDBC Pool、Apache Commons DBCP、C3P0、Druid等等。

三,实际应用

1,准备数据库以及表和基本数据

本文测试多库的情况,所以我们需要创建最少两个库进行测试。数据库sql我就不提供了,各位根据自己方便手动去创建吧。我这里简单创建两个库和三张表。如下图所示

2,基本框架准备(启动类就不展示了,有需要请看博主其它文档)

2.1 pom依赖
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.5.4</version>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.20</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.12.0</version> <!-- 这里是最新版本 -->
    </dependency>
<!--    日志框架-->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.5</version> <!-- 你可以替换为其他版本 -->
    </dependency>

    <!-- mysql 连接 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
      <version>2.5.4</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.17</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.2.0</version>
    </dependency>
2.2 application.properties

这里密码采用了加密的方式,运行时会自动解密,如果不知道怎么做的请查看SpringBoot启动自动解密加密配置项_springboot environment 配置项解密-CSDN博客

spring.profiles.active=dev,database
#mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
datasource1.url=jdbc:mysql://localhost:3306/rojertest?serverTimezone=Asia/Tokyo
datasource1.username=root
datasource1.password={decrypt}bGoxMDA0MDE4Mjc3

datasource2.url=jdbc:mysql://localhost:3306/roejrtest?serverTimezone=Asia/Tokyo
datasource2.username=root
datasource2.password={decrypt}bGoxMDA0MDE4Mjc3
2.3 HikariCP配置
#HikariCP 配置信息
#连接超时时间,指连接数据库时最大等待时间,单位是毫秒
spring.datasource.hikari.connection-timeout=3000
#连接空闲超时时间,指连接在连接池中保持空闲状态的最大时间,超过此时间连接将被释放,单位是毫秒
spring.datasource.hikari.idle-timeout=3000
#连接池的最大连接数,指连接池中允许的最大连接数量
spring.datasource.hikari.maximum-pool-size=10
#连接池的最小空闲连接数,指连接池中保持的最小空闲连接数量。
spring.datasource.hikari.minimum-idle=5
#设置连接的事务隔离级别
#1,DEFAULT:使用数据库系统的默认隔离级别。
#2,READ_UNCOMMITTED:允许事务读取未提交的数据更改。这是最低的隔离级别,它允许事务读取未提交的更改,可能会导致脏读、不可重复读和幻读等问题。
#3,READ_COMMITTED:确保一个事务只能读取到已经提交的数据更改。在这个级别下,事务不会读取到其他事务未提交的更改,可以避免脏读,但仍可能存在不可重复读和幻读的问题。
#4,REPEATABLE_READ:确保一个事务可以多次读取相同的数据而不受其他事务的影响。在这个级别下,事务不会读取到其他事务已提交的更改,可以避免脏读和不可重复读,但仍可能存在幻读的问题。
#5,SERIALIZABLE:最高的隔离级别,确保事务之间完全隔离,每个事务都像是在独立运行。在这个级别下,事务不会读取到其他事务已提交或未提交的更改,可以避免脏读、不可重复读和幻读,但是会降低并发性能。
spring.datasource.hikari.transaction-isolation=DEFAULT
#连接验证超时时间,指连接在被取出后最大等待数据库验证的时间,单位是毫秒
spring.datasource.hikari.validation-timeout=3000
#用于测试连接的 SQL 查询语句
spring.datasource.hikari.connection-test-query=SHOW TABLES
2.3 日志输出配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!-- 定义输出到控制台的日志记录器 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 设置日志输出格式 -->
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--打印数据库连接池日志信息-->
    <logger name="com.zaxxer.hikari" level="DEBUG"/>
    <!--打印sql信息-->
    <logger name="com.luojie.dao" level="DEBUG"/>

    <!-- 设置根日志级别为 INFO -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/> <!-- 将日志输出到控制台 -->
    </root>

</configuration>
2.4 datasourceConfig 编写(重要)
package com.luojie.config;

import com.zaxxer.hikari.HikariDataSource;
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.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.luojie.dao.mapper1", sqlSessionFactoryRef = "sqlSessionFactory1")
public class DataSource1Config {

    @Value("${datasource1.url}")
    private String url;
    @Value("${datasource1.username}")
    private String username;
    @Value("${datasource1.password}")
    private String password;

    @Bean(name = "dataSource1")
    public DataSource dataSource1() {
        return DataSourceBuilder.create()
                .url(url)
                .username(username)
                .password(password)
                // 使用HikariCP数据连接池管理
                .type(HikariDataSource.class)
                .build();
    }

    @Bean(name = "sqlSessionFactory1")
    public SqlSessionFactory sqlSessionFactory1(@Qualifier("dataSource1") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:rojerTestMapper/mapper1/*.xml"));
        return sessionFactoryBean.getObject();
    }
}
package com.luojie.config;

import com.zaxxer.hikari.HikariDataSource;
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.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.luojie.dao.mapper2", sqlSessionFactoryRef = "sqlSessionFactory2")
public class DataSource2Config {

    @Value("${datasource2.url}")
    private String url;
    @Value("${datasource2.username}")
    private String username;
    @Value("${datasource2.password}")
    private String password;

    @Bean(name = "dataSource2")
    public DataSource dataSource1() {
        return DataSourceBuilder.create()
                .url(url)
                .username(username)
                .password(password)
                // 使用HikariCP数据连接池管理
                .type(HikariDataSource.class)
                .build();
    }

    @Bean(name = "sqlSessionFactory2")
    public SqlSessionFactory sqlSessionFactory1(@Qualifier("dataSource2") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:rojerTestMapper/mapper2/*.xml"));
        return sessionFactoryBean.getObject();
    }

}

3. 业务代码编写

3.1 controller 
package com.luojie.controller;

import com.luojie.controImpl.DatabaseTestImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DatabaseTestController {

    @Autowired
    DatabaseTestImpl test;

    @GetMapping("/database/test")
    public void test1() {
        test.add();
    }
}
3.2 impl
package com.luojie.controImpl;

import com.luojie.dao.mapper1.Mapper1;
import com.luojie.dao.mapper2.Mapper2;
import com.luojie.moudle.LibraryModel;
import com.luojie.moudle.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseTestImpl {

    @Autowired
    private Mapper1 mapper1;

    @Autowired
    private Mapper2 mapper2;

    public void add() {
        UserModel userModel = new UserModel();
        userModel.setUsername("Rojer");
        userModel.setSex("男");
        userModel.setUserid("007");
        userModel.setRoles("admin,member");
        userModel.setMoney("10");

        LibraryModel libraryModel = new LibraryModel();
        libraryModel.setId(1);
        libraryModel.setAmount(1);
        mapper2.addLibrary(libraryModel);
        mapper2.addUserBalance(userModel);
        mapper1.addUser(userModel);
    }
}
3.3 model文件
package com.luojie.moudle;

import lombok.Data;

@Data
public class UserModel {

    private String username;

    private String money;

    private String sex;

    private String roles;

    private String userid;
}
package com.luojie.moudle;

import lombok.Data;

import java.math.BigDecimal;

@Data
public class LibraryModel {

    private String name;

    private BigDecimal price;

    private int amount;

    private int id;
}
3.4 mapper接口

注意这里放的位置一定要与前面config中配置的一致

package com.luojie.dao.mapper1;

import com.luojie.moudle.UserModel;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface Mapper1 {
    void addUser(UserModel userModel);
}
package com.luojie.dao.mapper2;

import com.luojie.moudle.LibraryModel;
import com.luojie.moudle.UserModel;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface Mapper2 {

    void addUserBalance(UserModel model);

    void addLibrary(LibraryModel model);
}
3.5 mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--<mapper> 标签用于定义 Mapper XML 文件。-->
<!--namespace 属性指定了该 Mapper XML 文件对应的 Mapper 接口的类路径。-->
<mapper namespace="com.luojie.dao.mapper1.Mapper1">

    <select id="addUser">
        insert into userpro (`userid`, `roles`, `username`) values (#{userid}, #{roles}, #{username})
    </select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--<mapper> 标签用于定义 Mapper XML 文件。-->
<!--namespace 属性指定了该 Mapper XML 文件对应的 Mapper 接口的类路径。-->
<mapper namespace="com.luojie.dao.mapper2.Mapper2">

    <update id="addUserBalance" parameterType="com.luojie.moudle.UserModel">
        update user set money = money + #{money} where userid = #{userid}
    </update>

    <update id="addLibrary" parameterType="com.luojie.moudle.LibraryModel">
        update library set amount = amount + #{amount} where id = #{id}
    </update>
</mapper>

四,代码测试

sql和连接池都是正常打印日志的

整体执行ok

希望对各位大佬有帮助。麻烦加个关注点个赞谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/694658.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

音视频转为文字SuperVoiceToText

音视频转为文字SuperVoiceToText&#xff0c;它能够把视频或语音文件高效地转换为文字&#xff0c;它是基于最为先进的 AI 大模型&#xff0c;通过在海量语音资料上进行训练学习而造就&#xff0c;具备极为卓越的识别准确率。 不仅如此&#xff0c;它支持包括汉语、英语、日语…

Java Set系列集合的使用规则和场景(HashSet,LinkedHashSet,TreeSet)

Set集合 package SetDemo;import java.util.HashSet; import java.util.Iterator; import java.util.Set;public class SetDemo {public static void main(String[] args) {/*Set集合的特点&#xff1a;1.Set系列集合的特点&#xff1a;Set集合是一个存储元素不能重复的集合方…

如何下载BarTender软件及详细安装步骤

BarTender是美国海鸥科技推出的一款优秀的条码打印软件&#xff0c;应用于 WINDOWS95 、 98 、 NT 、 XP 、 2000 、 2003 和 3.1 版本&#xff0c; 产品支持广泛的条形码码制和条形码打印机&#xff0c; 不但支持条形码打印机而且支持激光打印机&#xff0c;还为世界知名品牌条…

Modbus主站和从站的区别

Modbus主站,从站 在工业自动化领域&#xff0c;Modbus是一种常用的通信协议&#xff0c;用于设备之间的数据交换。在Modbus通信中&#xff0c;主站和从站是两个关键的角色。了解主站和从站之间的区别对正确配置和管理Modbus网络至关重要。 Modbus主站的特点和功能 1.通信请求发…

嵌入式仪器模块:音频综测仪和自动化测试软件

• 24 位分辨率 • 192 KHz 采样率 • 支持多种模拟/数字音频信号的输入/输出 应用场景 • 音频信号分析&#xff1a;幅值、频率、占空比、THD、THDN 等指标 • 模拟音频测试&#xff1a;耳机、麦克风、扬声器测试&#xff0c;串扰测试 • 数字音频测试&#xff1a;平板电…

【DrissionPage】Linux上如何将https改为http

最近有个老板找我做一个自动化的程序&#xff0c;要求部署到Linux上 这是一个http协议的网站&#xff0c;chrome在默认设置下&#xff0c;会将http的网站识别成不安全的内容&#xff0c;然后自动将http转化成https访问 但是&#xff0c;这个http的网站它的加载项里既有http的…

Python基础——字符串

一、Python的字符串简介 Python中的字符串是一种计算机程序中常用的数据类型【可将字符串看作是一个由字母、数字、符号组成的序列容器】&#xff0c;字符串可以用来表示文本数据。 通常使用一对英文的单引号&#xff08;&#xff09;或者双引号&#xff08;"&#xff09;…

三维重建 虚拟内窥镜(VE)是什么?怎么实现 使用场景

1.虚拟内窥镜&#xff1a; 就是利用计算机图形学、虚拟现实、图像处理和科学可视化等信息处理技术仿真光学内窥镜对病人进行诊断的一种技术。 VE(Virtual Endoscopy)&#xff0c;虚拟内镜技术。这种CT重建图像可以模拟各种内镜检查的效果&#xff0c;它是假设视线位于所要观察…

【数据结构】队列——循环队列(详解)

目录 0 循环队列 1 特定条件下循环队列队/空队满判断条件 1.1 队列为空的条件 1.2 队列为满的条件 2 循环队列的实现 3 示例 4 注意事项 0 循环队列 循环队列&#xff08;Circular Queue&#xff09;是队列的一种实现方式&#xff0c;它通过将队列存储空间的最后一…

【Java】Hutool发送邮件功能

目录 开通qq邮箱的stmp实战pom.xmlapplication.ymlcontrollerservice实体类辅助类 需要实现一个通过邮箱找回密码的功能 正常来说&#xff0c;找回密码的验证码&#xff0c;一般来说&#xff0c;都是通过手机号来找回的居多&#xff0c;那为什么会有通过邮箱找回的方式该说不说…

Luminar Neo - AI智能修图软件超越PS和LR,简单易用又高效!

很多人都想美化自己的风景和人物的图片&#xff0c;得到更加美丽耀眼的效果。然而&#xff0c;专业摄影师和设计师在电脑上使用的后期工具如 Photoshop 和 LightRoom 过于复杂。 通常为了一些简单的效果&#xff0c;你必须学习许多教程。而一些针对小白用户的“一键式美颜/美化…

Python第二语言(八、Python包)

目录 1. 什么是Python包 2. 创包步骤 2.1 new包 2.2 查看创建的包 2.3 拖动文件到包下 3. 导入包 4. 安装第三方包 4.1 什么是第三方包 4.2 安装第三方包-pip 4.3 pip网络优化 1. 什么是Python包 包下有__init__.py就是包&#xff0c;无__init__.py就是文件夹。于Ja…

开发没有尽头,尽力既是完美

最近遇到了一些难题&#xff0c;开发系统总有一些地方没有考虑周全&#xff0c;偏偏用户使用的时候“完美复现”了这个隐藏的Bug...... 讲道理创业一年之久为了生存&#xff0c;我一直都有在做复盘&#xff0c;复盘的核心就是&#xff1a;如何提升营收、把控开发质量&#xff0…

gdb调试器

目录 一、前言 debug和release 二、调试操作 2.1、退出 quit 2.2、调试 run 2.3、打断点 b 2.4、查看断点 info b 2.5、查看代码 l 2.6、删除断点 d 2.7、逐过程 n 2.8、打印变量内容 p 2.9、逐语句&#xff08;进入函数&#xff09; s 2.10、查看函数调用堆栈 …

先进封装技术的一些优缺点探讨

半导体封装技术是半导体制造过程中的关键环节&#xff0c;它不仅保护了芯片免受物理损伤&#xff0c;还提供了电气连接和散热功能。随着技术的发展&#xff0c;出现了多种先进的封装技术&#xff0c;每种技术都有其特定的应用场景和优缺点。 --> 1. 传统封装技术 【优点】&…

微服务之基本介绍

一、微服务架构介绍 1、微服务架构演变过程 单体应用架构->垂直应用架构一>分布式架构一>SOA架构-->微服务架构 ① 单体应用架构 互联网早期&#xff0c; 一般的网站应用流量较小&#xff0c;只需一个应用&#xff0c;将所有功能代码都部署在一起就可以&#x…

嵌入式仪器模块:波形发生器模块(嵌入式)

• 16 位分辨率 • 125 MHz 刷新率 • 支持生成 FSK/ASK 信号 应用场景 • 生成任意标准波形或用户自定义波形 • 在特殊协议通信中模拟某个波形 • 无线充电&#xff08;信号调制&#xff09; 道114输出阻抗Low-ZLow-ZLow-Z输出范围 5 V 5 V 6 V耦合DCDCDC带宽4 MHz10 M…

【小沐学Python】Python实现Web服务器(CentOS下打包Flask)

文章目录 1、简介2、下载Python3、编译Python4、安装PyInstaller5、打包PyInstaller6、相关问题6.1 ImportError: urllib3 v2 only supports OpenSSL 1.1.1, currently the ssl module is compiled with OpenSSL 1.0.2k-fips 26 Jan 2017. See: https://github.com/urllib3/url…

AXI Quad SPI IP核中的STARTUPEn原语参数

启动STARTUPEn Primitive &#xff08;原语&#xff09;参数在 FPGA的主 SPI模式下非常有用。当你启用这个参数时&#xff0c;对于 7 系列设备&#xff0c;STARTUPE2 原语会被包含在设计中&#xff1b;而对于 UltraScale™ 设备&#xff0c;则是 STARTUPE3 原语。这些原语在 FP…

基于NodeJs 的Vue安装和创建项目

基于NodeJs 的Vue安装和创建项目 一、Node.js的下载与安装 下载地址&#xff1a; https://nodejs.org/en/download/prebuilt-installer 安装完之后&#xff0c;启动 cmd命令行&#xff0c;验证 Node.js 是否安装成功 二、配置npm的全局模块的存放路径以及缓存的路径 注&…