2016-04-11 47 views
0

我有一个包含列 id,teacher_idname的课程表。在PreparedStatement中获取错误的输出

这是我用来通过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

或者只是不匹配任何行;我会打赌你给美元甜甜圈,“新课程”给你一个这些领域的零课程。第1步是**总是**调试:[*如何调试小程序*](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) –

+0

您可能没有数据库中该“id”的数据。而且,您看到的结果是int类型的默认值。 – Sachin

回答

4

的错误是在这里:

resultSet = statement.executeQuery(query); 

你不是叫PreparedStatement#executeQuery,你打电话Statement#executeQueryStatementPreparedStatement的超级接口)。所以参数替换不会发生,你实际上将?发送到服务器。

将其更改为:

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

(是的,这是一个API的设计缺陷;也没有,你不是第一个掉进去。)


有有关代码,可以使用改善一些其他的东西:

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

  2. 试戴与资源语句可以使代码更短都和清晰

  3. 你不应该投的getConnectionprepareStatement的返回值。

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

  5. 关于该主题,您可以使用setMaxRows为驱动程序提供有关此方面的提示。

  6. 你的方法声明它能够抛出SQLException,因为它调用close这是完全正确的,但唯一有用SQLException实际上是被抓住了,记录下来,并通过代码抑制,从而宣告它的方法有点误导。

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

这里是一个例子,以上所述。它允许异常传播,因此错误(例外情况)不在正常的代码流中处理;它返回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 

这大概可以进一步改善,但你的想法。

+1

像魔术一样工作。谢谢。 – Zeus

+0

@Zeus:不用担心。我在答案的末尾添加了一个注释,可能会有用。请注意,试用资源需要JDK 7或更高版本。 –

+0

我只是无法尝试使用Eclipse的资源,这段代码看起来好多了。 – Zeus