gpt4 book ai didi

java - JDBC Pool——如何正确使用

转载 作者:行者123 更新时间:2023-11-28 22:40:13 27 4
gpt4 key购买 nike

我将 JDBC 池用于我的 Tomcat Web 应用程序。

当我阅读文档时,我需要获取连接、执行查询并关闭。关闭后,连接返回到池中。

我认为当查询数据库依赖于外部事件时方式 1 更好,对于每 5 秒运行一次的任务方式 2 更正确。

有人可以解释一下每 5 秒重复一次的任务使用哪种方式吗?

PS:我跳过了代码中的额外检查以使代码看起来可读。

方式 #1 从池中获取连接并每 5 秒关闭一次

Connection c = null;
Statement s = null;
ResultSet rs = null;
DataSource ds = ... Get DataSource ...

while(running) {
try {
c = ds.getConnection();
s = c.createStatement();
rs = s.executeQuery('SELECT data FROM my_table');
... do something with result ...
} catch (SQLException sec) {
... print exception ...
} finally {
try {
rs.close();
s.close();
c.close();
} catch (SQLException sec) { ... print exception ... }

... Thread sleep 5 seconds and repeat ...
}
}

方式 #2 在循环前获取连接并在循环后关闭,在循环内重新连接

Connection c = null;
Statement s = null;
ResultSet rs = null;
DataSource ds = ... Get DataSource ...

c = ds.getConnection();

while(running) {
try {
s = c.createStatement();
rs = s.executeQuery('SELECT data FROM my_table');
... do something with result ...
} catch (SQLException sec) {
... print exception ...
... if connection lost, try reconnect and execute query again ...
} finally {
try {
rs.close();
s.close();
} catch (SQLException sec) {
... print exception ...
}
... Thread sleep 5 seconds and repeat ...
}
}

c.close();

池配置

<Resource name="jdbc/pg_mega" auth="Container"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:6432/db"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
username="***" password="****"
defaultAutoCommit="true"
initialSize="1"
maxActive="300"
maxTotal="300"
maxIdle="20"
minIdle="5"
maxWait="10000"
validationQuery="select 1"
validationInterval="30000"
testWhileIdle="false"
testOnBorrow="true"
testOnReturn="false"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="30000"
/>

最佳答案

我认为最常见的模式是这样的:

    Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
try {
conn = ds.getConnection();
stmt = conn.prepareStatement(sqlStatement);
//
// ....
res = stmt.executeQuery();

// use the resultset

conn.commit();
} catch (SQLException e) {
// Manage the exception
try {
conn.rollback();
} catch (SQLException e1) {
// SWALLOW
}

} finally {
close(res);
close(stmt);
close(conn);
}

我使用这些辅助函数来安全关闭而无需太多样板,从 Java 7 开始您可以自动关闭,因此这些辅助函数不再有用。

public static void close(Connection conn) {
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
// SWALLOW
}
}

public static void close(Statement stmt) {
try {
if (stmt != null)

stmt.close();
} catch (SQLException e) {
// SWALLOW
}
}

public static void close(ResultSet res) {
try {
if (res != null)
res.close();
} catch (SQLException e) {
// SWALLOW
}
}

你真的应该确保在 finally 语句中关闭连接,如果你不关闭连接就会发生不好的事情,如果(例如)你的例子中的 rs 为空(不是那么困难)你就不会关闭连接。

从池中获取和释放连接不是性能问题,它发生在几微秒内,比任何可能的查询快数千倍。

你不急于释放连接的原因是事务,你想为整个事务保持同一个连接(没有办法绕过这个)。

当您提交(或回滚)时,您不再需要那个特殊的连接,所以只需释放它。

另一个提示,在finally中关闭连接,即使你catch SQL Exceptions,因为总是有Runtime Exceptions甚至Error(你不会catch),但finally即使遇到OutOfMemoryError或ClassDefNotFoundError或任何其他,连接将返回到池中。

最后但并非最不重要的是在断开连接的情况下将尝试重新连接的池,实际上池将丢弃无效连接并在需要时创建新的批处理。

你应该选择一个好的连接验证策略,一个糟糕的选择会导致获取连接的额外时间从而严重影响性能,或者从池中获取无效连接导致异常。

优化池就像许多其他性能调整任务一样:困难

例如:testOnBorrow="true" 将在获取连接之前访问数据库,这是安全的,但它会比不检查借用慢数十或数百时间。

testWhileIdle="true" 反而不太安全(您可能会获得无效连接)但速度要快得多,并且具有保持连接 Activity 的优势。

您必须考虑如何使用连接、如何处理错误、DB 在哪里(在同一台机器上、在 lan 上、在 wan 上)以及许多其他因素来选择。

关于java - JDBC Pool——如何正确使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42984766/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com