简体   繁体   English

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

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

Will closing the preparedStatement also close and return the connection to the connection pool?关闭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());
        }
    }

Bonus question:奖金问题:

I have created performance tests for creating a new connection each time an object needs one, Singleton connection and connection pool.每次 object 需要一个 Singleton 连接和连接池时,我都创建了用于创建新连接的性能测试。

Singleton - Fastest Singleton - 最快

Creating a new connection each time - Slower (1.2s than the one above)每次创建一个新连接 - 比上面的慢(1.2s)

Connection Pool - Slowest (First connection - 2-3s slower than the one above, following tests are 0.4s slower than the one above)连接池 - 最慢(第一次连接 - 比上述慢 2-3 秒,以下测试比上述慢 0.4 秒)

I am using Apache Commons DBCP for the connection pool.我正在使用 Apache Commons DBCP 作为连接池。

I thought using connection pools, would be just a little slower than Singleton connection.我认为使用连接池会比 Singleton 连接慢一点。

Have I done something wrong?我做错了什么吗?

You asked:您问:

Will closing the preparedStatement also close and return the connection to the connection pool?关闭preparedStatement也会关闭并将连接返回到连接池吗?

Start with the documentation :文档开始:

Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed.立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待它自动关闭时发生。 It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.通常最好在使用完资源后立即释放资源,以避免占用数据库资源。

Calling the method close on a Statement object that is already closed has no effect.对已关闭的 Statement object 调用方法 close 无效。

Note:When a Statement object is closed, its current ResultSet object, if one exists, is also closed.注意:当 Statement object 关闭时,其当前的 ResultSet object(如果存在)也将关闭。

No mention of closing the connection.没有提到关闭连接。

Try intuition: Do we ever run more than one statement in SQL?试试直觉:我们是否曾经在 SQL 中运行多个语句? Yes, obviously.是的,很明显。 So logically the connection needs to survive across multiple statements to be useful.所以从逻辑上讲,连接需要在多个语句中存活下来才能有用。

Lastly: Try it yourself, an empirical test.最后:自己尝试,经验测试。 Call Connection#isOpen after calling Statement#close .在调用Statement#close之后调用Connection#isOpen

➥ No, closing the statement does not close the connection. ➥ 不,关闭语句不会关闭连接。

For the simplest code, learn to use try-with-resources syntax to auto-close your database resources such as result set, statement, and connection.对于最简单的代码,学习使用try-with-resources语法来自动关闭您的数据库资源,例如结果集、语句和连接。 You'll find many examples of such code on this site, including some written by me.您会在此站点上找到许多此类代码的示例,包括我编写的一些示例。

As for connection pools, yes, calling close on a connection retrieved from a pool causes the connection object to be be returned to the pool.至于连接池,是的,对从池中检索到的连接调用close会导致连接 object 被返回到池中。 The pool may choose to re-use the connection, or the pool may choose to close the connection.池可以选择重用连接,或者池可以选择关闭连接。 (Not our concern.) (不是我们关心的问题。)

The only point to a connection pool is speed.连接池的唯一要点是速度。 If opening a connection to the database takes a significant amount of time, we can save that time by re-using existing connection.如果打开与数据库的连接需要大量时间,我们可以通过重用现有连接来节省时间。 Generating and re-using connections is the job of a connection pool.生成和重用连接是连接池的工作。

If a connection pool is showing the slowest results in your testing, then here is something seriously wrong with either your pool or your tests .如果连接池在您的测试中显示最慢的结果,那么您的连接池或您的测试存在严重错误 You did not reveal to us your tests, so we cannot help there.您没有向我们透露您的测试,因此我们无法提供帮助。 Note: As Marmite Bomber commented , be sure your tests do not include the time needed to establish the connection pool.注意:正如Marmite Bomber 所评论的,请确保您的测试包括建立连接池所需的时间。

Frankly, I have found in my experience that opening a database connection does not take a significant amount of time.坦率地说,根据我的经验,我发现打开数据库连接并不需要很长时间。 Furthermore, the details involved in properly implementing a connection pool are complex and treacherous as evidenced by the list of failed and abandoned connection pool implementation projects.此外,正确实施连接池所涉及的细节是复杂和危险的,这从失败和放弃的连接池实施项目列表中可以看出。 That, combined with the inherent risks such as a transaction being left open on a retrieved connection, led me to avoiding the use of connection pools.再加上诸如事务在检索到的连接上保持打开状态等固有风险,导致我避免使用连接池。 I would posit that using a connection pool before collecting proof of an actual problem is a case of premature optimization .我认为在收集实际问题的证据之前使用连接池是过早优化的一种情况。

I suggest using an implementation of the interface DataSource as a way to mask from the rest of your code whether you are using a pool and to hide which pool implementation you are currently using.我建议使用接口DataSource的实现作为屏蔽代码的 rest 的方法,无论您是否正在使用池并隐藏您当前正在使用的池实现。 Using DataSource gives you the flexibility to to change between using or not using a connection pool, and the flexibility to change between pools.使用DataSource可以让您灵活地在使用或不使用连接池之间进行切换,以及在池之间进行切换。 Those changes become deployment choices, with no need to change your app programming.这些更改成为部署选择,无需更改您的应用程序编程。

Pools are meant to improve performance, not degrade it.池旨在提高性能,而不是降低性能。 DBCP is naive, complicated, and outdated. DBCP 是幼稚的、复杂的和过时的。 I don't think it's appropriate for a production application, especially when so many drivers support pooling in their DataSource natively.我认为它不适合生产应用程序,尤其是当有这么多驱动程序在其 DataSource 本地支持池时。 The entire pool gets locked the whole time a new connection attempt is made to the database.在对数据库进行新连接尝试的整个过程中,整个池都会被锁定。 So, if something happens to your database that results in slow connections or timeouts, other threads are blocked when they try to return a connection to the pool—even though they are done using a database.因此,如果您的数据库发生了导致连接缓慢或超时的问题,则其他线程在尝试将连接返回到池时会被阻止——即使它们是使用数据库完成的。 Even C3PO performs terribly.甚至 C3PO 的表现也很糟糕。 Please try using one of the two connection pools tomcat_connection_pool or HikariCP请尝试使用两个连接池之一 tomcat_connection_poolHikariCP

Now coming to your main part of the question if you have closed the connection correctly?如果您已正确关闭连接,现在进入问题的主要部分? Whenever you use a connection pool and you fetch an available connection from the pool you need not have to close the connection that you fetched in your Dao layer.每当您使用连接池并从池中获取可用连接时,您无需关闭在 Dao 层中获取的连接。 The pool manages the connections that you have created and each connection that the pool lends has a timeout associated with it before which it has to return to the pool.池管理您创建的连接,并且池借出的每个连接都有与之关联的超时,在此之前它必须返回池。 When the pool is shut down all the connections shutdown too.当池关闭时,所有连接也会关闭。

For more information on how to configure these properties in your connection pool.有关如何在连接池中配置这些属性的更多信息。 Please check the links above for each of the connection pools.请检查每个连接池的上述链接。

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

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