【问题标题】:Am I closing the DB connection correctly? JDBC - DBCP我是否正确关闭了数据库连接? JDBC-DBCP
【发布时间】:2021-04-27 22:30:38
【问题描述】:

关闭preparedStatement是否也会关闭并将连接返回到连接池?

public void insertProjectIntoDatabase(Project project) {
        String insertProjectIntoDatabase =
                "INSERT INTO projects(Project_Id, Project_Name, Project_StartDate, Deadline) " +
                        "VALUES (?, ?, ?, ?)";
        try {
            preparedStatement = DBCPDataSource.getConnection().prepareStatement(insertProjectIntoDatabase);
            preparedStatement.setInt(1, project.getProjectId());
            preparedStatement.setString(2, project.getName());
            preparedStatement.setDate(3, java.sql.Date.valueOf(project.getStartDate()));
            preparedStatement.setDate(4, java.sql.Date.valueOf(project.getDeadline()));
            preparedStatement.execute();

            preparedStatement.close();
        }
        catch (SQLException e)
        {
            System.out.println("Error happened in ProjectRepository at insertProjectIntoDatabase(): " + e.getMessage());
        }
    }

额外问题:

我已经创建了性能测试,用于在每次对象需要一个新连接时创建一个新连接、单例连接和连接池。

单例 - 最快

每次都创建一个新连接 - 比上面的慢(1.2s)

连接池 - 最慢(第一次连接 - 比上一个慢 2-3 秒,以下测试比上一个慢 0.4 秒)

我正在使用 Apache Commons DBCP 作为连接池。

我认为使用连接池会比单例连接慢一点。

我做错了吗?

【问题讨论】:

  • 可能你应该保存连接并在完成后关闭()stackoverflow.com/questions/28209955/…
  • 您可能证明启动一个连接池需要更长的时间来打开一个单个连接,这是正确的。
  • 每个问题只问一个问题。

标签: java jdbc


【解决方案1】:

你问:

关闭preparedStatement是否也会关闭并将连接返回到连接池?

the documentation开头:

立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待它自动关闭时发生。通常最好在使用完资源后立即释放资源,以避免占用数据库资源。

对已关闭的 Statement 对象调用 close 方法无效。

注意:当一个Statement对象被关闭时,它当前的ResultSet对象,如果存在的话,也被关闭。

没有提到关闭连接。

试试直觉:我们是否曾经在 SQL 中运行过多个语句?是的,很明显。所以从逻辑上讲,连接需要在多个语句中存活下来才能有用。

最后:自己尝试一下,一个经验测试。拨打Statement#close后拨打Connection#isOpen

➥ 不,关闭语句不会关闭连接。

对于最简单的代码,学习使用try-with-resources 语法来自动关闭您的数据库资源,例如结果集、语句和连接。您会在此站点上找到许多此类代码的示例,包括我编写的一些示例。

对于连接池,是的,对从池中检索到的连接调用close 会导致连接对象返回到池中。池可以选择重用连接,或者池可以选择关闭连接。 (不是我们关心的问题。)

连接池的唯一要点是速度。如果打开与数据库的连接需要大量时间,我们可以通过重用现有连接来节省时间。生成和重用连接是连接池的工作。

如果连接池在您的测试中显示最慢的结果,则说明您的连接池或测试存在严重问题。您没有向我们透露您的测试,因此我们无法提供帮助。注意:作为Marmite Bomber commented,请确保您的测试包括建立连接池所需的时间。

坦率地说,根据我的经验,我发现打开数据库连接不会花费大量时间。此外,正确实施连接池所涉及的细节是复杂和危险的,失败和放弃的连接池实施项目清单证明了这一点。再加上诸如事务在检索到的连接上保持打开状态等固有风险,导致我避免使用连接池。我认为在收集实际问题的证据之前使用连接池是一种过早优化的情况。

我建议使用接口DataSource 的实现来屏蔽其余代码是否正在使用池并隐藏当前正在使用的池实现。使用DataSource 可以让您灵活地在使用或不使用连接池之间进行切换,以及在池之间进行切换。这些更改成为部署选择,无需更改您的应用程序编程。

【讨论】:

    【解决方案2】:

    池旨在提高性能,而不是降低性能。 DBCP 是幼稚的、复杂的和过时的。 我认为它不适合生产应用程序,尤其是当有如此多的驱动程序原生支持在其 DataSource 中进行池化时。在对数据库进行新连接尝试的整个过程中,整个池都会被锁定。因此,如果您的数据库发生了导致连接缓慢或超时的问题,则其他线程在尝试将连接返回到池时会被阻止——即使它们是使用数据库完成的。 甚至 C3PO 的表现也很糟糕。 请尝试使用tomcat_connection_poolHikariCP 两个连接池之一

    如果您正确关闭了连接,现在进入问题的主要部分? 每当您使用连接池并从池中获取可用连接时,您无需关闭在 Dao 层中获取的连接。池管理您创建的连接,并且池借出的每个连接都有与之关联的超时,在此之前它必须返回池。当池关闭时,所有连接也会关闭。

    有关如何在连接池中配置这些属性的更多信息。请检查每个连接池的上述链接。

    【讨论】:

    • 告诉 OP 他们不需要关闭连接是很糟糕的建议。
    • 我同意 Nathan Hughes 的观点,告诉 OP 不要关闭连接是个坏建议。关闭连接是将它们返回到池中以供重用。没有在适当的时候关闭它们会导致你的程序需要比实际需要更多的连接。
    猜你喜欢
    • 2015-06-24
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 1970-01-01
    相关资源
    最近更新 更多