【问题标题】:Correction to try/finally更正尝试/最终
【发布时间】:2019-06-17 08:11:49
【问题描述】:

我正在尝试使用 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;
}

【问题讨论】:

  • 似乎不喜欢它。 - 这不是很有技术含量吗?错误是什么?
  • 从安全方面我会说这个 sql 查询容易受到 sql 注入的影响。不要使用"SELECT * FROM person_c WHERE LAST_NAME= '" + lastName + "'";。请改用参数化语句。 More Information to SQL Injections
  • 谢谢 MapReduce - 我以后会记住的。目前我们只是在做练习,因为我是学徒。我已经完成了代码,但正在整理边缘。
  • @MapReduce - OMG,我怎么会错过这些查询中有字符串 concat 的事实?!

标签: java try-catch finally


【解决方案1】:

该代码中有三个不相关的问题:

  1. 理论上,close 可以扔。如果您之前的任何 close 调用抛出,以后的调用将不会完成。此外,如果异常已经发生,来自close 调用的异常将覆盖它,隐藏真正的问题。解决方法是使用try-with-resources

  2. 您正在通过PreparedStatement 呼叫executeQuery(String)。永远不要那样做,它将PreparedStatement 视为只是Statement。 (这是一个 API 设计错误。)改为将查询传递给 prepareStatement

  3. 不要使用字符串连接将值放入查询中。这就是PreparedStatement 的重点:安全地参数化查询。 (让我给你介绍my friend Bobby...)

所以处理所有这三个:

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;
}

【讨论】:

  • 谢谢克劳德 - 你非常有帮助。会试一试:-)
  • @HywelGriffiths - 不用担心。恐怕我之前错过了您代码中的字符串连接,并且在我更新的示例中我也忘记从executeQuery 中删除query 现在都已修复,对此感到抱歉。
猜你喜欢
  • 2011-09-08
  • 2014-11-05
  • 2021-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2015-01-17
  • 2010-09-21
相关资源
最近更新 更多