DD异常,并清理数据库资源:有一个干净的解决方案吗?

时间:2012-05-25 10:20:20

标签: jdbc findbugs pmd dataflow

这是我们写的一段代码:

    public CustomerTO getCustomerByCustDel(final String cust, final int del)
            throws SQLException {
        final PreparedStatement query = getFetchByCustDel();
        ResultSet records = null;
        try {
            query.setString(1, cust);
            query.setInt(2, del);
            records = query.executeQuery();

            return this.getCustomer(records);
        } finally {
            if (records != null) {
                records.close();
            }
            query.close();
        }
    }

如果省略'finally'块,则会使数据库资源悬空,这显然是一个潜在的问题。但是,如果您执行我在此处所做的操作 - 在** try **块之外将ResultSet设置为null,然后将其设置为块内所需的值 - PMD报告'DD异常'。在文档中,DD异常描述如下:

DataflowAnomalyAnalysis:数据流分析跟踪数据流上不同路径上的变量的本地定义,未定义和引用。从这些信息中可以发现各种问题。 [...] DD - 异常:重新定义了最近定义的变量。这是不祥的,但不一定是一个错误。

如果在块外部声明ResultSet而不设置值,则在执行 if(records!= null)测试时,正确地得到'变量可能未初始化'错误。< / p>

现在,在我看来,我在这里使用不是一个错误。但有没有一种干净的重写方式,不会触发PMD警告?我并不特别想要禁用PMD的DataFlowAnomalyAnalysis规则,因为识别UR和DU异常实际上是有用的;但是这些DD异常让我怀疑自己可以做得更好 - 而且,如果没有更好的方法可以做到这一点,那么它们就会变得混乱(我应该看看是否可以重写PMD规则)

2 个答案:

答案 0 :(得分:2)

我认为这更清楚:

PreparedStatement query = getFetchByCustDel();
try {
    query.setString(1, cust);
    query.setInt(2, del);
    ResultSet records = query.executeQuery();
    try {
        return this.getCustomer(records);
    } finally {
        records.close();
    }
} finally {
    query.close();
}

此外,在您的版本中,如果records.close()抛出异常,则查询不会被关闭。

答案 1 :(得分:1)

我认为DD异常注释比一个特征更多的bug 此外,释放资源的方式有点不完整,例如

PreparedStatement pstmt = null;
Statement st = null; 

try {
    ...
} catch (final Exception e) {
    ...
} finally {
    try{
        if (pstmt != null) {
            pstmt.close();
        }
    } catch (final Exception e) {
        e.printStackTrace(System.err);
    } finally {
        try {
            if (st != null) {
                st.close();
            }
        } catch (final Exception e) {
            e.printStackTrace(System.err);
        }
    }
}

此外这不是正确的,因为你应该关闭那样的资源

PreparedStatement pstmt = null;
Throwable th = null;

try {
    ...
} catch (final Throwable e) {
    <something here>
    th = e;
    throw e;
} finally {
    if (th == null) {
        pstmt.close();
    } else {
        try {
            if (pstmt != null) {
                pstmt.close();
            }
        } catch (Throwable u) {
        }
    }
}