Исправление, чтобы попробовать / наконец - PullRequest
0 голосов
/ 17 июня 2019

Я пытаюсь закрыть свой набор результатов, соединение и утверждение с помощью try / finally, но Sonar, похоже, это не нравится.Какую ошибку я делаю и почему они не закрываются?Спасибо.

public static List<String> findByName(String firstName, String lastName) throws SQLException {

    /*Connects  to  table and contexts a statement to this connection. Creates the appropriate statement (query)
    according to the first name and last name nulls, builds an array from the ResultSet that is created.*/
    List<String> nameList = new ArrayList();
    String query;

    Connection conn = null;
    Statement preparedStatement = null;
    ResultSet allNames = null;

    try {
        conn = DriverManager.getConnection(getHost(), getuName(), getuPass());
        preparedStatement = conn.createStatement();
        if (firstName == null && lastName == null) {
            query = "SELECT * FROM person_c";
        } else if (firstName == null) {
            query = "SELECT * FROM person_c WHERE LAST_NAME= '" + lastName + "'";
        } else if (lastName == null) {
            query = "SELECT * FROM person_c where FIRST_NAME= '" + firstName + "'";
        } else {
            query = "SELECT * FROM person_c where FIRST_NAME =  '" + firstName + "'" + "AND LAST_NAME= '" + lastName + "'";
        }
        allNames = preparedStatement.executeQuery(query);
        while (allNames.next()) {
            nameList.add(allNames.getString("FIRST_NAME") + "  " + allNames.getString("LAST_NAME"));
        }
    } finally {
        if (allNames != null) allNames.close();
        if (preparedStatement!=null)  preparedStatement.close();
        if (conn!=null) conn.close();
    }
    return nameList;
}

1 Ответ

3 голосов
/ 17 июня 2019

В этом коде есть три не связанные проблемы:

  1. Теоретически, close можно бросить. Если какой-либо из ваших предыдущих вызовов close сработает, последующие не будут выполнены. Кроме того, если исключение уже выполняется, исключение из этих вызовов close переопределит его, скрывая истинную проблему. Решение состоит в том, чтобы использовать try-with-resources .

  2. Вы звоните executeQuery(String) на PreparedStatement. Никогда не делай этого, он рассматривает PreparedStatement, как будто это просто Statement. (Это ошибка разработки API.) Вместо этого передайте запрос в prepareStatement.

  3. Не используйте конкатенацию строк для помещения значений в запрос. В этом смысл PreparedStatement: для безопасной параметризации запроса. (Позвольте представить вам моего друга Бобби ...)

Итак, обработаем все три из них:

public static List<String> findByName(String firstName, String lastName) throws SQLException {

    /*Connects  to  table and contexts a statement to this connection. Creates the appropriate statement (query)
    according to the first name and last name nulls, builds an array from the ResultSet that is created.*/
    List<String> nameList = new ArrayList();
    String query;

    try (
        Connection conn = DriverManager.getConnection(getHost(), getuName(), getuPass());
    ) {
        if (firstName == null && lastName == null) {
            query = "SELECT * FROM person_c";
        } else if (firstName == null) {
            query = "SELECT * FROM person_c WHERE LAST_NAME = ?";
        } else if (lastName == null) {
            query = "SELECT * FROM person_c where FIRST_NAME = ?";
        } else {
            query = "SELECT * FROM person_c where FIRST_NAME = ? AND LAST_NAME = ?";
        }
        try (
            Statement preparedStatement = conn.createStatement(query);
        ) {
            int n = 1;
            if (firstName != null) {
                preparedStatement.setString(n++, firstName);
            }
            if (lastName != null) {
                preparedStatement.setString(n++, lastName);
            }
            try (
                ResultSet allNames = preparedStatement.executeQuery();
            ) {
                while (allNames.next()) {
                    nameList.add(allNames.getString("FIRST_NAME") + "  " + allNames.getString("LAST_NAME"));
                }
            }
        }
    }
    return nameList;
}
...