首页 Java java教程 什么是光池?

什么是光池?

Jan 07, 2025 pm 04:08 PM

O que é o hikari pool?

什么是光池?

BlueSky 上的一篇帖子中的这个简单问题让我得到了一个我认为非常酷的解释。我来这里是为了完成它。

在具体的上下文中,正在谈论 Hikari 连接池。但是,如果 Hikari 是一个连接池,那么“池”会是什么?

首先,泳池概念

在解释什么是 HikariCP 之前,我们需要先解释一下连接池是什么。为了解释连接池,我们需要解释

我们可以用经济学来类比吗?这是一个与现实世界充满缺陷和不准确的历史经济类比,但是来吧,为了解释而迅速停止你的怀疑!它是独立的。

想象一下您是中世纪时代的领主/女士。你拿着工具来进行农民的工作。并且您希望它们能够工作。那么如何保证这一点呢?如果工具是你的?你需要给农民提供工具,很简单。

所以想象一下这种情况:你的农民需要一把锄头来除草,所以他去那里向你要一把锄头。你会给他锄头并继续生活。但如果他不归还,他的锄头怎么办?总有一天会结束的……

交出锄头的另一种选择是制作锄头。您是这些土地的领主/女士,因此您可以联系铁匠,将金属熔炼成锄头的形状并将其安装到手柄中。但这不是你可以在没有农民坐在候诊室的情况下立即生产的东西。为了实现这个新功能,您需要大量的时间和精力。

现在,如果农民在一天结束时归还锄头,第二天它就可以供其他农民使用。

在这里,您正在控制锄头池是一种设计模式,指示您可以执行以下操作:

  • 向他要一个元素
  • 返回元素

对象中的其他常见内容:

  • 通过在池中注册来按需创建更多对象的能力
  • 能够从中销毁对象(或将其与解除关联)

连接到 JDBC 数据库

那么,让我们离HikariCP更近一些吧。这里我们来谈谈Java中的数据库连接。

在java中,我们要求建立与数据库的连接。有直接连接选项,您需要直接了解要调用哪些类以及一些细节,或者只是享受服务发现选项。

先验地,为了使用服务发现,服务提供者会提供一种方法来注册他所提供的内容,然后“服务发现”会跟踪它以查看谁可以服务该请求。

服务发现案例:pstmt-null-safe

我曾经遇到过需要建立 JDBC 连接来与数据库通信的情况。但是,我的 JDBC 驱动程序不接受使用 null 作为值,只接受直接在查询中使用 null。那么我做了什么?司机顶司机!

总体思路如下。想象一下,我有一个查询,我想将值插入到:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在想象一下我正在处理这个值第一次插入到银行中。为此,我需要将其保留为 ID=1、CONTENT=first 和 PARENT=null,因为毕竟没有这样的父记录(毕竟它是第一个)。

自然会做什么:

try (final var pstmt = conn.prepareStatement(
                """
                INSERT INTO some_table (id, content, parent)
                VALUES (?, ?, ?)
                """)) {

    pstmt.setInt(1, 1);
    pstmt.setString(2, "first");
    pstmt.setNull(3, Types.INTGEGER); // java.sql.Types
    pstmt.executeUpdate(); // de fato altere o valor
}
登录后复制
登录后复制
登录后复制

我想继续这样使用它,毕竟这是惯用的使用方式。根据丘比特的说法,“I”来自“惯用语”。拥有惯用代码的想法正是为了“减少不必要的心理负担”。

为了解决这个问题,我的选择是:将prepareStatement留到executeUpdate之前的最后一刻。因此,我存储了要应用的所有空值,当我意识到我实际上需要一个空值时,我运行字符串替换并生成一个新查询,并且这个新查询将实际执行。

在这种情况下,我从:
开始

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

所以,我必须输入这些值:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)

-- 1, 'first', NULL
登录后复制
登录后复制
登录后复制

但我实际上无法使用 null,所以我创建了一个键来标识第三位是 null:

-- (value, value, NULL)
INSERT INTO some_table (id, content, parent)
VALUES (?, ?, NULL)
-- 1, 'first'
登录后复制
登录后复制
登录后复制

在这种情况下,我准备这个新字符串并根据要求放置参数。

好吧,也就是说,我如何向我的应用程序表明我需要使用 JDBC 驱动程序?我如何注册?

相关项目是 Pstmt Null Safe。基本上,Java 类加载器有一个神奇之处,即加载 jar 时,它会查找名为 META-INF 的元数据文件夹。对于 JDBC 驱动程序,META-INF/services/java.sql.Driver,我用实现 java.sql.Driver 的类记录了它:br.com.softsite.pstmtnullsafe.jdbc.PstmtNullSafeDriver。

根据 java.sql.Driver 文档,每个驱动程序都应该创建自己的实例并向 DriverManager 注册。我是这样实现的:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

静态块自行加载。我们如何知道哪个连接应该由我的驱动程序管理?该调用是通过 DriverManager#getConnection(String url) 进行的。我们有 URL 来询问驱动程序是否接受连接。约定(这里又是惯用的使用方式)是将其作为 URL 方案的前缀。因为我希望我的驱动程序连接到另一个驱动程序之上,所以我使用了以下方案:

try (final var pstmt = conn.prepareStatement(
                """
                INSERT INTO some_table (id, content, parent)
                VALUES (?, ?, ?)
                """)) {

    pstmt.setInt(1, 1);
    pstmt.setString(2, "first");
    pstmt.setNull(3, Types.INTGEGER); // java.sql.Types
    pstmt.executeUpdate(); // de fato altere o valor
}
登录后复制
登录后复制
登录后复制

因此,为了执行测试,我连接了 SQLite,并使用 Xerial 指示器通过连接 URI 请求内存中连接:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

为了“封装”连接,我的约定表明我不重复 jdbc:,所以:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)

-- 1, 'first', NULL
登录后复制
登录后复制
登录后复制

剖析上面的 URI:

-- (value, value, NULL)
INSERT INTO some_table (id, content, parent)
VALUES (?, ?, NULL)
-- 1, 'first'
登录后复制
登录后复制
登录后复制

好的,你如何表明这一点?如果我可以打开连接,Driver#acceptsURL 必须返回 true。我可以这样做:

public static final PstmtNullSafeDriver instance;

static {
    instance = new PstmtNullSafeDriver();
    try {
        DriverManager.registerDriver(instance);
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
登录后复制

但是如果我尝试加载不存在的驱动程序,这表明什么?没什么,下次会出问题的。这并不好,理想的情况是从一开始就崩溃。因此,为此,我将尝试从下面加载驱动程序,如果不能,我将返回 false:

jdbc:pstmt-nullsafe:<url de conexão sem jdbc:>
\__/ \____________/
 |    |
 |    Nome do meu driver
 Padrão para indicar JDBC
登录后复制

实际的驱动程序代码还有一些与此处讨论的 HikariCP、DataSource、JDBC 或本文讨论的主题无关的要点。

因此,当请求与 DriverManager 的“空安全”连接时,它首先找到我的驱动程序,然后我的驱动程序递归地尝试检查是否有可能在后台建立连接。确认有一个驱动程序能够处理这个问题,我说是的,这是可能的。

Java中JDBC连接的使用模式

Connection 接口实现了 AutoCloseable 接口。这意味着您获取连接,根据需要使用该连接,然后关闭该连接。对此使用一些间接连接是非常标准的,或者,如果您直接使用连接,请在 try-with-resources:
块中使用它

jdbc:sqlite::memory:
登录后复制

现在,创建连接的过程是一个昂贵的过程。而且服务发现过程并不是完全免费的。因此,理想的情况是保存驱动程序,然后生成连接。让我们一点一点地开发它。

首先,我们需要有一个可以通过驱动程序启动的对象。它可以很容易地是一个全局对象、一个注入的 Spring 组件或类似的东西。我们称之为 JdbcConnector:

jdbc:pstmt-nullsafe:sqlite::memory:
登录后复制

getJdbcConnection() 的一种可能实现是依赖于该函数包含的状态:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

到目前为止一切都很顺利。但是……还记得最初的例子吗?农民在工具池中索要一把锄头?那么……我们要考虑到这一点吗?我们可以将连接返回到,而不是实际关闭连接。为了正确性,我会防止多个同时访问,但我不会担心这里的效率。

我们假设我有一个名为 ConnectionDelegator 的类。它实现了所有 Connection 方法,但它自己不执行任何操作,它仅委托给作为构造函数传递给它的连接。例如,对于 isClosed():
方法

try (final var pstmt = conn.prepareStatement(
                """
                INSERT INTO some_table (id, content, parent)
                VALUES (?, ?, ?)
                """)) {

    pstmt.setInt(1, 1);
    pstmt.setString(2, "first");
    pstmt.setNull(3, Types.INTGEGER); // java.sql.Types
    pstmt.executeUpdate(); // de fato altere o valor
}
登录后复制
登录后复制
登录后复制

其他方法依此类推。它是抽象的,因为一个简单的事实是,当我使用它时,我想强迫自己做一些除了简单委托之外的事情。

好吧,我们走吧。这个想法是,将请求连接,该连接可能存在也可能不存在。如果存在,我将其包装在这个新类中,以便在关闭连接时将其返回到 pool。嗯,所以我要在 close() 方法中做一些事情...好吧,我们先包装一下。让我们将 getConnection() 保留为同步以避免并发问题:

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

好的,如果我的连接中有元素,我会使用它们直到它为空。但它永远不会被填满!那么我们要解决这个问题吗?当它关闭时,我们可以将其返回

INSERT INTO some_table (id, content, parent)
VALUES (?, ?, ?)

-- 1, 'first', NULL
登录后复制
登录后复制
登录后复制

好的,现在当您使用完连接后,它会被发送回
泳池。这不满足 Connection#close() 方法的文档,因为在文档中它提到它释放与此连接相关的所有 JDBC 资源。这意味着我需要保留所有语句、结果集、PreparedStatements 等的记录。我们可以通过在 ConnectionDelegator 上创建一个名为 closeAllInnerResources() 的受保护方法来处理此问题。并在 close() 中调用它:

-- (value, value, NULL)
INSERT INTO some_table (id, content, parent)
VALUES (?, ?, NULL)
-- 1, 'first'
登录后复制
登录后复制
登录后复制

这样我们就可以根据需要向我返回连接,并且能够形成资源池

你知道Java给提供连接的对象起什么名字吗?数据源。您知道 Java 对 DataSource 还说了什么吗?从概念上讲,有一些类型。在这些类型中,最相关的 2 种是:

  • 基本:它不进行池化,它请求连接,它只是创建并返回它
  • 池化:其中存在与银行的连接池

这里我们经历了始终创建连接(基本类型)以及演变为数据源的过程
合并

什么是光CP?

HikariCP 是一个数据源。具体来说,是一个池化数据源。但他有一个特点:他是所有人中速度最快的。为了保证这个速度,在应用程序生命周期中使用的连接中,HikariCP 制定了一个秘密:它已经创建了所有可用的连接。因此,当 getConnection 到达时,HikariCP 只需要检查连接池

如果你想更深入地研究这个主题,你可以查看 Baeldung 上有关该主题的这篇文章,也可以查看 github 上的存储库。

以上是什么是光池?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

公司安全软件导致应用无法运行?如何排查和解决? 公司安全软件导致应用无法运行?如何排查和解决? Apr 19, 2025 pm 04:51 PM

公司安全软件导致部分应用无法正常运行的排查与解决方法许多公司为了保障内部网络安全,会部署安全软件。...

如何使用MapStruct简化系统对接中的字段映射问题? 如何使用MapStruct简化系统对接中的字段映射问题? Apr 19, 2025 pm 06:21 PM

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

如何优雅地获取实体类变量名构建数据库查询条件? 如何优雅地获取实体类变量名构建数据库查询条件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

如何将姓名转换为数字以实现排序并保持群组中的一致性? 如何将姓名转换为数字以实现排序并保持群组中的一致性? Apr 19, 2025 pm 11:30 PM

将姓名转换为数字以实现排序的解决方案在许多应用场景中,用户可能需要在群组中进行排序,尤其是在一个用...

IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本启动Spring...

Java对象如何安全地转换为数组? Java对象如何安全地转换为数组? Apr 19, 2025 pm 11:33 PM

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品? 电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品? Apr 19, 2025 pm 11:27 PM

电商平台SKU和SPU表设计详解本文将探讨电商平台中SKU和SPU的数据库设计问题,特别是如何处理用户自定义销售属...

使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名构建查询条件? 使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名构建查询条件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名以构建查询条件,是一个常见的难题。本文将针...

See all articles