在PreparedStatement中输出错误

时间:2016-04-11 15:02:57

标签: java sql jdbc

我有一个带有列的课程表, idteacher_idname

这是我用来获取id的课程的方法。

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

1 个答案:

答案 0 :(得分:4)

错误在这里:

resultSet = statement.executeQuery(query);

您没有致电PreparedStatement#executeQuery,而是致电Statement#executeQueryStatementPreparedStatement的超级接口)。因此,参数替换不会发生,而您实际上是将?发送到服务器。

将其更改为:

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

(是的,这是一个API设计缺陷;不,你不是第一个陷入它的人。)

该代码还有一些其他可以改进的地方:

  1. 即使发生异常,您也总是返回Course。最佳做法是允许异常传播给调用者;第二好的做法是将某种标志返回给调用者发生错误,例如null

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

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

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

  5. 关于该主题,您可以使用setMaxRows向驱动程序提供相关提示。

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

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

  8. 这是一个包含上述内容的例子。它允许传播异常,因此在正常的代码流中不处理错误(异常条件);如果没有匹配的课程,它会返回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
    

    这可能会进一步改善,但你明白了。