创建 preparedstatement 的多个实例
Creating multiple instances of preparedstatement
我是 jdbc 编程新手。我多次创建 PreparedStatement
的实例并将其分配给相同的引用变量。在创建 PreparedStatement
的第二个实例之前,我是否需要关闭 PreparedStatement
的第一个实例?
oPrepStmt = oRoot.con.prepareStatement(strSql);
if (strProviderType.length() > 0) {
strSql += " and users.usertype IN (?)";
// DO I need to close prepare statement, before creating another instance of preparestatement and assigning to same reference variable.
// i.e. oPrepStmt.close();
oPrepStmt = oRoot.con.prepareStatement(strSql);
oPrepStmt.setString(2,strProviderType);
}
oPrepStmt.setInt(1,oRoot.getTrUserId());
未关闭preparedstatement第一个实例是否导致资源泄漏?
JDBC 语句实现 AutoCloseable
,因此表明在不再需要时应明确关闭。
An object that may hold resources (such as file or socket handles)
until it is closed. The close() method of an AutoCloseable object is
called automatically when exiting a try-with-resources block for which
the object has been declared in the resource specification header.
This construction ensures prompt release, avoiding resource exhaustion
exceptions and errors that may otherwise occur.
因此,正如 Javadoc 所建议的,使用 try-with-resources 语句:
try (PreparedStatement pstmt = oRoot.con.prepareStatement(strSql)) {
... run sql commands ...
}
在您的示例中,您创建了一个语句并在某些情况下将其丢弃。最好避免这种情况并像这样写:
boolean checkUserType = strProviderType.length();
try (PreparedStatement pstmt = oRoot.con.prepareStatement(checkUserType ? strSql : strSql + " and users.usertype IN (?)") {
oPrepStmt.setInt(1,oRoot.getTrUserId());
if (checkUserType)
oPrepStmt.setString(2,strProviderType);
...
}
您应该始终在完成语句后将其关闭。在某些 databases/JDBC 驱动程序中,语句也有一个服务器端句柄。不关闭该语句将使该句柄在服务器上保持打开状态,从而导致不必要的资源消耗(主要是内存,但它可能会锁定某些元数据对象)。
最重要的是,在驱动程序端不关闭语句还可能会消耗额外的资源(内存、连接事件的侦听器等)。因此建议尽快关闭。
驱动程序最终可能会通过终结器或在您关闭连接时取消分配它,但依赖它并不是一个好主意(例如,连接池中的连接并不总是正确关闭语句时他们被送回游泳池等)。
现在关于您的具体问题,您应该将代码修改为:
if (strProviderType.length() > 0) {
strSql += " and users.usertype IN (?)";
}
try (PreparedStatement oPrepStmt = oRoot.con.prepareStatement(strSql)) {
oPrepStmt.setInt(1,oRoot.getTrUserId());
if (strProviderType.length() > 0) {
oPrepStmt.setString(2, strProviderType);
}
oPrepStmt.execute(); // or executeQuery or executeUpdate
}
我还包含一个 try-with-resources 以确保语句尽快关闭。
顺便说一句,您对 IN(?)
的使用可能不会在大多数(所有?)数据库上像这样工作。参见 PreparedStatement IN clause alternatives?
我是 jdbc 编程新手。我多次创建 PreparedStatement
的实例并将其分配给相同的引用变量。在创建 PreparedStatement
的第二个实例之前,我是否需要关闭 PreparedStatement
的第一个实例?
oPrepStmt = oRoot.con.prepareStatement(strSql);
if (strProviderType.length() > 0) {
strSql += " and users.usertype IN (?)";
// DO I need to close prepare statement, before creating another instance of preparestatement and assigning to same reference variable.
// i.e. oPrepStmt.close();
oPrepStmt = oRoot.con.prepareStatement(strSql);
oPrepStmt.setString(2,strProviderType);
}
oPrepStmt.setInt(1,oRoot.getTrUserId());
未关闭preparedstatement第一个实例是否导致资源泄漏?
JDBC 语句实现 AutoCloseable
,因此表明在不再需要时应明确关闭。
An object that may hold resources (such as file or socket handles) until it is closed. The close() method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header. This construction ensures prompt release, avoiding resource exhaustion exceptions and errors that may otherwise occur.
因此,正如 Javadoc 所建议的,使用 try-with-resources 语句:
try (PreparedStatement pstmt = oRoot.con.prepareStatement(strSql)) {
... run sql commands ...
}
在您的示例中,您创建了一个语句并在某些情况下将其丢弃。最好避免这种情况并像这样写:
boolean checkUserType = strProviderType.length();
try (PreparedStatement pstmt = oRoot.con.prepareStatement(checkUserType ? strSql : strSql + " and users.usertype IN (?)") {
oPrepStmt.setInt(1,oRoot.getTrUserId());
if (checkUserType)
oPrepStmt.setString(2,strProviderType);
...
}
您应该始终在完成语句后将其关闭。在某些 databases/JDBC 驱动程序中,语句也有一个服务器端句柄。不关闭该语句将使该句柄在服务器上保持打开状态,从而导致不必要的资源消耗(主要是内存,但它可能会锁定某些元数据对象)。
最重要的是,在驱动程序端不关闭语句还可能会消耗额外的资源(内存、连接事件的侦听器等)。因此建议尽快关闭。
驱动程序最终可能会通过终结器或在您关闭连接时取消分配它,但依赖它并不是一个好主意(例如,连接池中的连接并不总是正确关闭语句时他们被送回游泳池等)。
现在关于您的具体问题,您应该将代码修改为:
if (strProviderType.length() > 0) {
strSql += " and users.usertype IN (?)";
}
try (PreparedStatement oPrepStmt = oRoot.con.prepareStatement(strSql)) {
oPrepStmt.setInt(1,oRoot.getTrUserId());
if (strProviderType.length() > 0) {
oPrepStmt.setString(2, strProviderType);
}
oPrepStmt.execute(); // or executeQuery or executeUpdate
}
我还包含一个 try-with-resources 以确保语句尽快关闭。
顺便说一句,您对 IN(?)
的使用可能不会在大多数(所有?)数据库上像这样工作。参见 PreparedStatement IN clause alternatives?