创建preparestatement的多个实例

时间:2016-03-11 10:27:58

标签: java database jdbc prepared-statement

我是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实例会导致资源泄漏吗?

2 个答案:

答案 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?