我有一个包含列的类(class)表,
id
, teacher_id
和name
.
这是我用来通过 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
(Statement
是 PreparedStatement
的超接口(interface))。因此,参数替换并未发生,您实际上是将 ?
发送到服务器。
将其更改为:
resultSet = statement.executeQuery();
// No argument here ---------------^
(是的,这是一个 API 设计缺陷;不,您不是第一个陷入其中的人。)
<小时/>该代码还有一些其他方面需要改进:
即使发生异常,您也始终会返回
类(class)
。最佳实践是允许异常传播给调用者;第二个最佳实践是向调用者返回某种发生错误的标志,例如null
。try-with-resources 语句可以使代码更短、更清晰
您不必强制转换
getConnection
或prepareStatement
的返回值。您正在使用
while
,但您只期望得到一个结果。if
会更有意义。关于该主题,您可以使用
setMaxRows
向驾驶员提供这方面的提示。 .您的方法声明它可以抛出
SQLException
,这实际上是正确的,因为它调用close
,但唯一有用SQLException
实际上被代码捕获、记录和抑制,使得在方法上声明它有点误导。我被告知现代 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/