我是否正确关闭了数据库连接? JDBC - DBCP
Am I closing the DB connection correctly? JDBC - DBCP
关闭preparedStatement是否也会关闭return与连接池的连接?
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());
}
}
加分题:
我已经创建了每次对象需要一个新连接时创建一个新连接的性能测试,Singleton 连接和连接池。
单例 - 最快
每次都创建一个新连接 - 慢(比上面那个慢1.2s)
连接池 - 最慢(第一个连接 - 比上面的慢 2-3s,后面的测试比上面的慢 0.4s)
我正在为连接池使用 Apache Commons DBCP。
我认为使用连接池会比单例连接慢一点。
我是不是做错了什么?
池旨在提高性能,而不是降低性能。 DBCP 幼稚、复杂且过时。
我认为它不适合生产应用程序,尤其是当这么多驱动程序原生支持在其数据源中进行池化时。在对数据库进行新连接尝试的整个过程中,整个池都会被锁定。因此,如果您的数据库发生某些导致连接缓慢或超时的事情,其他线程在尝试 return 连接到池时会被阻塞——即使它们是使用数据库完成的。
甚至 C3PO 的表现也很糟糕。
请尝试使用两个连接池之一 tomcat_connection_pool or HikariCP
如果您正确关闭了连接,现在进入问题的主要部分?
每当您使用连接池并从池中获取可用连接时,您无需关闭在 Dao 层中获取的连接。池管理您创建的连接,并且池借出的每个连接都有一个与之关联的超时,在此之前它必须 return 到池。当池关闭时,所有连接也会关闭。
有关如何在连接池中配置这些属性的更多信息。请检查上面每个连接池的链接。
您问的是:
Will closing the preparedStatement also close and return the connection to the connection pool?
从 the documentation 开始:
Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. 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.
Note:When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
没有提到关闭连接。
试试直觉:我们是否曾经 运行 在 SQL 中有不止一个陈述?是的,很明显。所以从逻辑上讲,连接需要在多个语句中存在才能有用。
最后:亲身体验,实证检验。调用 Connection#isOpen
after calling Statement#close
.
➥ 不,关闭语句不会关闭连接。
对于最简单的代码,学习使用 try-with-resources 语法来 auto-close 您的数据库资源,例如结果集、语句和连接。您会在此站点上找到此类代码的许多示例,包括我编写的一些示例。
至于连接池,是的,对从池中检索到的连接调用 close
会导致连接 object 返回到池中。池可以选择 re-use 连接,也可以选择关闭连接。 (不关我们的事。)
连接池的唯一一点就是速度。如果打开与数据库的连接需要大量时间,我们可以通过 re-using 节省时间现有连接。生成和 re-using 连接是连接池的工作。
如果连接池在您的测试中显示最慢的结果,那么您的池或测试存在严重错误。您没有向我们透露您的测试,因此我们无能为力。注意:由于 Marmite Bomber commented,请确保您的测试不包括建立连接池所需的时间。
坦率地说,根据我的经验,我发现打开数据库连接不会花费大量时间。此外,正确实施连接池所涉及的细节是复杂和危险的,失败和放弃的连接池实施项目列表证明了这一点。再加上固有的风险,例如事务在检索到的连接上保持打开状态,导致我避免使用连接池。我认为在收集实际问题的证据之前使用连接池是 过早优化.
的情况
我建议使用接口 DataSource
的实现来屏蔽其余代码是否正在使用池并隐藏当前正在使用的池实现。使用 DataSource
使您可以灵活地在使用或不使用连接池之间进行更改,以及在池之间进行更改的灵活性。这些更改成为部署选择,无需更改您的应用编程。
关闭preparedStatement是否也会关闭return与连接池的连接?
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());
}
}
加分题:
我已经创建了每次对象需要一个新连接时创建一个新连接的性能测试,Singleton 连接和连接池。
单例 - 最快
每次都创建一个新连接 - 慢(比上面那个慢1.2s)
连接池 - 最慢(第一个连接 - 比上面的慢 2-3s,后面的测试比上面的慢 0.4s)
我正在为连接池使用 Apache Commons DBCP。
我认为使用连接池会比单例连接慢一点。
我是不是做错了什么?
池旨在提高性能,而不是降低性能。 DBCP 幼稚、复杂且过时。 我认为它不适合生产应用程序,尤其是当这么多驱动程序原生支持在其数据源中进行池化时。在对数据库进行新连接尝试的整个过程中,整个池都会被锁定。因此,如果您的数据库发生某些导致连接缓慢或超时的事情,其他线程在尝试 return 连接到池时会被阻塞——即使它们是使用数据库完成的。 甚至 C3PO 的表现也很糟糕。 请尝试使用两个连接池之一 tomcat_connection_pool or HikariCP
如果您正确关闭了连接,现在进入问题的主要部分? 每当您使用连接池并从池中获取可用连接时,您无需关闭在 Dao 层中获取的连接。池管理您创建的连接,并且池借出的每个连接都有一个与之关联的超时,在此之前它必须 return 到池。当池关闭时,所有连接也会关闭。
有关如何在连接池中配置这些属性的更多信息。请检查上面每个连接池的链接。
您问的是:
Will closing the preparedStatement also close and return the connection to the connection pool?
从 the documentation 开始:
Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. 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.
Note:When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
没有提到关闭连接。
试试直觉:我们是否曾经 运行 在 SQL 中有不止一个陈述?是的,很明显。所以从逻辑上讲,连接需要在多个语句中存在才能有用。
最后:亲身体验,实证检验。调用 Connection#isOpen
after calling Statement#close
.
➥ 不,关闭语句不会关闭连接。
对于最简单的代码,学习使用 try-with-resources 语法来 auto-close 您的数据库资源,例如结果集、语句和连接。您会在此站点上找到此类代码的许多示例,包括我编写的一些示例。
至于连接池,是的,对从池中检索到的连接调用 close
会导致连接 object 返回到池中。池可以选择 re-use 连接,也可以选择关闭连接。 (不关我们的事。)
连接池的唯一一点就是速度。如果打开与数据库的连接需要大量时间,我们可以通过 re-using 节省时间现有连接。生成和 re-using 连接是连接池的工作。
如果连接池在您的测试中显示最慢的结果,那么您的池或测试存在严重错误。您没有向我们透露您的测试,因此我们无能为力。注意:由于 Marmite Bomber commented,请确保您的测试不包括建立连接池所需的时间。
坦率地说,根据我的经验,我发现打开数据库连接不会花费大量时间。此外,正确实施连接池所涉及的细节是复杂和危险的,失败和放弃的连接池实施项目列表证明了这一点。再加上固有的风险,例如事务在检索到的连接上保持打开状态,导致我避免使用连接池。我认为在收集实际问题的证据之前使用连接池是 过早优化.
的情况我建议使用接口 DataSource
的实现来屏蔽其余代码是否正在使用池并隐藏当前正在使用的池实现。使用 DataSource
使您可以灵活地在使用或不使用连接池之间进行更改,以及在池之间进行更改的灵活性。这些更改成为部署选择,无需更改您的应用编程。