java - 在PreparedStatement中得到错误的输出

标签 java sql jdbc

我有一个包含列的类(class)表, id , teacher_idname .

这是我用来通过 id 获取类(class)的方法。

public static Course getById(int id) throws SQLException {
        String query = "SELECT * FROM courses WHERE id = ?" ;
        Course course = new Course();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try{
                DriverManager.registerDriver(new com.mysql.jdbc.Driver ());
                connection = (Connection) DriverManager.getConnection(ConnectDb.CONN_STRING, ConnectDb.USERNAME, ConnectDb.PASSWORD);
                statement = (PreparedStatement) connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE,
                        ResultSet.CONCUR_READ_ONLY);
                statement.setInt(1, id);
                resultSet = statement.executeQuery(query);

                while (resultSet.next()) {
                    course.setId(resultSet.getInt("id"));
                    course.setName(resultSet.getString("name"));
                    course.setTeacherId(resultSet.getInt("teacher_id"));

                }
            }catch (SQLException e) {
                System.err.println(e);

            }finally{
                if (resultSet != null) resultSet.close();;
                if (statement != null) statement.close();
                if(connection != null) connection.close();
            }

        return course;



    }// end of method

当我运行此方法时,我得到输出 id :0, Teacher_id : 0

服务器日志显示我有一个 SQLException

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1

最佳答案

错误在这里:

resultSet = statement.executeQuery(query);

你没有调用 PreparedStatement#executeQuery ,您正在调用Statement#executeQuery (StatementPreparedStatement 的超接口(interface))。因此,参数替换并未发生,您实际上是将 ? 发送到服务器。

将其更改为:

resultSet = statement.executeQuery();
// No argument here ---------------^

(是的,这是一个 API 设计缺陷;不,您不是第一个陷入其中的人。)

<小时/>

该代码还有一些其他方面需要改进:

  1. 即使发生异常,您也始终会返回类(class)。最佳实践是允许异常传播给调用者;第二个最佳实践是向调用者返回某种发生错误的标志,例如 null

  2. try-with-resources 语句可以使代码更短、更清晰

  3. 您不必强制转换 getConnectionprepareStatement 的返回值。

  4. 您正在使用 while,但您只期望得到一个结果。 if 会更有意义。

  5. 关于该主题,您可以使用 setMaxRows 向驾驶员提供这方面的提示。 .

  6. 您的方法声明它可以抛出 SQLException,这实际上是正确的,因为它调用 close,但唯一有用 SQLException 实际上被代码捕获、记录和抑制,使得在方法上声明它有点误导。

  7. 我被告知现代 JDBC 驱动程序不再需要 registerDriver 调用。 (我个人已经有一段时间没有使用 JDBC 了,所以...)

这是一个结合上述内容的示例。它允许异常传播,因此错误(异常情况)不会在正常的代码流中得到处理;如果没有匹配的类(class),则返回 null:

public static Course getById(int id) throws SQLException {
    String query = "SELECT * FROM courses WHERE id = ?";

    try (
        Connection connection = DriverManager.getConnection(ConnectDb.CONN_STRING, ConnectDb.USERNAME, ConnectDb.PASSWORD);
        PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
    ) {
        statement.setInt(1, id);
        statement.setMaxRows(1);
        try (
            ResultSet resultSet = statement.executeQuery();
        ) {
            if (resultSet.next()) {
                Course course = new Course();
                course.setId(resultSet.getInt("id"));
                course.setName(resultSet.getString("name"));
                course.setTeacherId(resultSet.getInt("teacher_id"));
                return course;
            }

            // No matching course
            return null;
        }
    }

} // end of method

这可能还可以进一步改进,但你明白了。

关于java - 在PreparedStatement中得到错误的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36552387/

相关文章:

java - 包含阿拉伯和西方字符的字符串连接

java - 检查方法参数是否为空?

java - 从 Bouncy CaSTLe 中的文本创建 RSA 公钥时出现问题

MySQL 从另一列中选择查询 : SUM() rows with a distinct value,

sql - 根据以前的日期查询带有参数的记录

java - 将 JAR 从 $HOME/jre/lib/ext 移动到 Gradle 时出现 JDBC 错误

java - 从另一个获取运行 Java 程序的输出

sql - 获取 PostgreSQL 中小数点后非零的记录

java - ResultSetMetaData getScale 返回 0

java - SQL 错误 : 0, SQLState: 08S01 通信链路故障