Аномалия DD и очистка ресурсов базы данных: есть ли чистое решение?

Вот кусок кода, который мы все написали:

    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', вы оставите ресурсы базы данных подвешенными, что, очевидно, является потенциальной проблемой. Однако, если вы сделаете то, что я сделал здесь — установите для ResultSet значение null вне блока **try**, а затем установите его в желаемое значение внутри блока — PMD сообщит об «аномалии DD». В документации аномалия DD описывается следующим образом:

DataflowAnomalyAnalysis: The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow.From those informations there can be found various problems. [...] DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug.

Если вы объявите ResultSet вне блока, не задав значения, вы справедливо получите ошибку "переменная, возможно, не была инициализирована" при выполнении теста if (records != null).

Теперь, на мой взгляд, мое использование здесь не является ошибкой. Но есть ли способ чистой перезаписи, которая не вызывала бы предупреждения PMD? Я не особенно хочу отключать правило DataFlowAnomalyAnalysis PMD, поскольку выявление аномалий UR и DU было бы действительно полезно; но эти аномалии DD заставляют меня подозревать, что я мог бы сделать что-то лучше - и, если нет лучшего способа сделать это, они составляют беспорядок (и, возможно, мне следует подумать, могу ли я переписать правило PMD)


person Simon Brooke    schedule 25.05.2012    source источник


Ответы (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() выдает исключение.

person TimK    schedule 25.05.2012

Я думаю, что примечание об аномалии DD — это скорее ошибка, чем фича
Кроме того, то, как вы освобождаете ресурсы, немного несовершенно, например.

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) {
        }
    }
}
person Ivan Ivanov    schedule 25.09.2013