SpringBoot工程下实现HikariCP连接池的整合

2024-01-04 08:48

本文主要是介绍SpringBoot工程下实现HikariCP连接池的整合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

池化思想分析

池化思想是我们项目开发过程中的一种非常重要的思想,如整数池,字符串池,对象池、连接池、线程池等都是池化思想的一种应用,都是通过复用对象,以减少因创建和释放对象所带来的资源消耗,进而来提升系统性能。例如Integer对象的内部池应用,代码如下:
package com.cy.java.pool;
public class TestInteger01 {public static void main(String[] args) {Integer n1=100;//Integer.valueOf(100) 编译时优化Integer n2=100;Integer n3=200;Integer n4=200;//池中没有则new Integer(200)System.out.println(n1==n2);//trueSystem.out.println(n3==n4);//false }}

数据库连接池简介

背景分析

目前开发过程中应用程序与数据库交互时,“获得连接”或“释放连接”是非常消耗系统资源的两个过程,频繁地进行数据库连接的建立和关闭会极大影响系统的性能,若多线程并发量很大,这样耗时的数据库连接就可能让系统变得卡顿。因为TCP连接的创建开支十分昂贵,并且数据库所能承载的TCP并发连接数也有限制,针对这种场景,数据库连接池应运而生。如下图所示:

在这里插入图片描述

思考:假如现在是让你去设计一个连接池,你会从什么角度进行设计?第一:物理存储结构(基于什么结构去存储数据)第二:基于什么算法从池中取连接?第三:基于什么算法从池中移除连接?第四:当池中没有连接时,基于什么方式处理连接请求?第五:池是可以共享,我们需要考虑池在访问 时并发安全?

连接池原理分析

在系统初始化的时候,在内存中开辟一片空间,将一定数量的数据库连接作为对象存储在对象池里,并对外提供数据库连接的获取和归还方法。用户访问数据库时,并不是建立一个新的连接,而是从数据库连接池中取出一个已有的空闲连接对象;使用完毕归还后的连接也不会马上关闭,而是由数据库连接池统一管理回收,为下一次借用做好准备。如果由于高并发请求导致数据库连接池中的连接被借用完毕,其他线程就会等待,直到有连接被归还。整个过程中,连接并不会关闭,而是源源不断地循环使用,有借有还。数据库连接池还可以通过设置其参数来控制连接池中的初始连接数、连接的上下限数,以及每个连接的最大使用次数、最大空闲时间等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

Java中的连接池

Java官方,为了在应用程序中更好的应用连接池技术,定义了一套数据源规范,例如javax.sql.DataSource接口,基于这个接口,很多团队或个人创建了不同的连接池对象。然后我们的应用程序中通过耦合与DataSource接口,便可以方便的切换不同厂商的连接池。Java项目中通过连接池获取连接的一个基本过程,如下图所示:

在这里插入图片描述

在上图中,用户通过DataSource对象的getConnection()方法,获取一个连接。假如池中有连接,则直接将连接返回给用户。假如池中没有连接,则会调用Dirver(驱动,由数据库厂商进行实现)对象的connect方法从数据库获取,拿到连接以后,可以将连接在池中放一份,然后将连接返回给调用方。连接需求方再次需要连接时,可以从池中获取,用完以后再还给池对象。数据库连接池在Java数据库相关中间件产品群中,应该算是底层最基础的一类产品,作为企业应用开发必不可少的组件,无数天才们为我们贡献了一个又一个的优秀产品,它们有的随时代发展,功成身退,有的则还在不断迭代,老而弥坚,更有新生代产品,或性能无敌,或功能全面。目前市场上常见的连接池有DBCP、C3P0,DRUID,HikariCP等。

HikariCP连接池测试

单元测试API设计及应用分析,如图所示:

在这里插入图片描述

在项目中添加单元测试类及测试方法,代码如下:
package com.cy.pj.common.datasource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class DataSourceTests {@Autowiredprivate DataSource dataSource;@Testpublic void testConnection() throws Exception{System.out.println(dataSource.getConnection());}
}
在当前测试类中我们需要:
掌握单元测试类、测试方法编写规范。理解DataSource的设计规范及规范的实现。分析在测试类中dataSource属性指向的对象是谁?分析在测试类中DataSource的实现类对象由谁创建和管理?思考基于DataSource接口获取连接的基本过程是怎样的?

测试BUG分析

数据库不存在,如图所示:

在这里插入图片描述

连接错误:数据库连接不上,如图所示:

在这里插入图片描述

基于HikariCP实现JDBC操作

业务分析

####### 基于HikariCP,借助JDBC技术访问商品库中的数据。

API 架构设计

####### 基于业务,进行API设计,如图所示:
在这里插入图片描述

业务时序图分析

####### 基于业务需求,进行商品查询过程的时序图设计,如图所示:
在这里插入图片描述

业务代码设计及实现

第一步:定义GoodsDao接口,例如:
package com.cy.pj.goods.dao;
import java.util.List;
import java.util.Map;
/*** 商品模块数据访问层接口*/
public interface GoodsDao {/*** 查询所有商品信息,将每一行记录存储到一个map对象,然后将多个存储到list集合.*/ List<Map<String,Object>> findGoods();
}
第二部:创建GoodsDao接口实现类,代码如下:
package com.cy.pj.goods.dao;
/*** 此对象为一个商品数据层访问对象,现在要求在此类中定义一个方法,这个方法基于JDBC从从数据库获取商品信息,并将其封装到map集合,要求一个行记录一个map对象(key为表中字段名,值为字段名对应的值),多个map存储到list集合. @Repository此注解通常用于描述数据层实现类对象,本质上就是一个特殊的@Component, 都是要交给spring框架管理的一个Bean对象*/
@Repository
public class DefaultGoodsDao implements  GoodsDao{@Autowiredprivate DataSource dataSource;//hikariCP/**查询商品信息,一行记录映射为内存中的一个map对象*/public List<Map<String,Object>> findGoods(){Connection conn=null;//java.sql.*Statement stmt=null;ResultSet rs=null;String sql="select * from tb_goods";//1.获取连接(从连接池获取)try {conn=dataSource.getConnection();//2.创建statement对象stmt=conn.createStatement();//3.发送sqlrs=stmt.executeQuery(sql);//4.处理结果List<Map<String,Object>> list=new ArrayList<>();while(rs.next()){//循环一次取一行,一行记录映射为一个map对象list.add( rowMap(rs));//将存储了一行记录的map对象再存储到list集合}return list;}catch (SQLException e){e.printStackTrace();throw new RuntimeException(e);//转换为非检查异常(编译时不检测的异常)}finally{//5. 释放资源close(rs,stmt,conn);}}
定义行映射方法:
       private Map<String,Object> rowMap(ResultSet rs)throws SQLException{Map<String,Object> rowMap=new HashMap<>();//方法1映射//rowMap.put("id",rs.getInt("id"));//rowMap.put("name",rs.getString("name"));//rowMap.put("remark",rs.getString("remark"));//rowMap.put("createdTime",rs.getTimestamp("createdTime"));//方法2映射ResultSetMetaData rsmd=rs.getMetaData();//获取元数据(包括表中的字段名)int columnCount=rsmd.getColumnCount();//获取列的数量for(int i=0;i<columnCount;i++){rowMap.put(rsmd.getColumnLabel(i+1),rs.getObject(rsmd.getColumnLabel(i+1)));//getColumnLabel(i+1);获取表中字段名或字段名对应的别名}return rowMap;}

####### 定义释放资源的方法:

       private void close(ResultSet rs,Statement stmt,Connection conn){if(rs!=null)try{rs.close();}catch(Exception e){e.printStackTrace();}if(stmt!=null)try{stmt.close();}catch(Exception e){e.printStackTrace();}//这里的连接是返回到了池中if(conn!=null)try{conn.close();}catch(Exception e){e.printStackTrace();}}
}
测试代码的编写及运行

####### 定义单元测试类,并对其查询过程进行单元测试,例如:

package com.cy.pj.goods.dao;@SpringBootTest
public class GoodsDaoTests {@Autowiredprivate GoodsDao goodsDao;@Testvoid testFindGoods(){List<Map<String,Object>> list= goodsDao.findGoods();for(Map<String,Object> map:list){System.out.println(map);}}}

总结:

数据库连接池的为我们的开发及运行带来了很多优点,如下:

1)资源重用更佳
由于数据库连接得到复用,减少了大量创建和关闭连接带来的开销,也大大减少了内存琐碎和数据库临时进程、线程的数量,使得整体系统的运行更加平稳。
2)系统优化更简便
使用了数据库连接池以后,由于资源重用,大大减少了频繁关闭连接的开销,大大减低了TIME_WAIT的出现频率。
3)系统响应更快
数据库连接池在应用初始化的过程中一般都会提前准备好一些数据库连接,业务请求可以直接使用已经创建的连接,而不需要等待创建连接的开销。初始化数据库连接配合资源重用,使得数据库连接池可以大大缩短系统整体响应时间。
4)连接管理更灵活
数据库连接池作为一款中间件,用户可以自行配置连接的最小数量、最大数量、最大空闲时间、获取连接超时间、心跳检测等。另外,用户也可以结合新的技术趋势,增加数据库连接池的动态配置、监控、故障演习等一系列实用的功能。

这篇关于SpringBoot工程下实现HikariCP连接池的整合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/568778

相关文章

Nginx 配置跨域的实现及常见问题解决

《Nginx配置跨域的实现及常见问题解决》本文主要介绍了Nginx配置跨域的实现及常见问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来... 目录1. 跨域1.1 同源策略1.2 跨域资源共享(CORS)2. Nginx 配置跨域的场景2.1

Python中提取文件名扩展名的多种方法实现

《Python中提取文件名扩展名的多种方法实现》在Python编程中,经常会遇到需要从文件名中提取扩展名的场景,Python提供了多种方法来实现这一功能,不同方法适用于不同的场景和需求,包括os.pa... 目录技术背景实现步骤方法一:使用os.path.splitext方法二:使用pathlib模块方法三

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解