繁体   English   中英

我是否正确关闭了数据库连接? JDBC-DBCP

[英]Am I closing the DB connection correctly? JDBC - DBCP

关闭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());
        }
    }

奖金问题:

每次 object 需要一个 Singleton 连接和连接池时,我都创建了用于创建新连接的性能测试。

Singleton - 最快

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

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

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

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

我做错了什么吗?

您问:

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

文档开始:

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

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

注意:当 Statement object 关闭时,其当前的 ResultSet object(如果存在)也将关闭。

没有提到关闭连接。

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

最后:自己尝试,经验测试。 在调用Statement#close之后调用Connection#isOpen

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

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

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

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

如果连接池在您的测试中显示最慢的结果,那么您的连接池或您的测试存在严重错误 您没有向我们透露您的测试,因此我们无法提供帮助。 注意:正如Marmite Bomber 所评论的,请确保您的测试包括建立连接池所需的时间。

坦率地说,根据我的经验,我发现打开数据库连接并不需要很长时间。 此外,正确实施连接池所涉及的细节是复杂和危险的,这从失败和放弃的连接池实施项目列表中可以看出。 再加上诸如事务在检索到的连接上保持打开状态等固有风险,导致我避免使用连接池。 我认为在收集实际问题的证据之前使用连接池是过早优化的一种情况。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM