我是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());
未公开的第一个readystatement实例会导致资源泄漏吗?
答案 0 :(得分:3)
JDBC语句实现AutoCloseable
,因此表明在不再需要时应明确关闭。
可以保存资源的对象(例如文件或套接字句柄) 直到关闭AutoCloseable对象的close()方法是 退出try-with-resources块时自动调用 该对象已在资源规范头中声明。 这种结构可确保快速释放,避免资源耗尽 可能发生的异常和错误。
正如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);
...
}
答案 1 :(得分:2)
完成后,您应该始终关闭语句。在某些数据库/ 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?