2016-04-11 31 views
0

私は、カラムが id,teacher_idおよびnameのコーステーブルを用意しています。PreparedStatementで間違った出力を取得しています

これはIDでコースを取得するために使用しているメソッドです。

私はこの方法を実行すると、私は出力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 

: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); 

あなたはStatement#executeQuery(を呼んでいる、PreparedStatement#executeQueryを呼び出していませんはPreparedStatementのスーパーインターフェイスです)。したがって、パラメータの置換は行われておらず、実際には?をサーバーに送信しています。

変更し、それに:

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

(そして、はい、これはAPIの設計上の欠陥であり、いや、あなたがそれに陥り最初じゃない。)


があります。改善を使用することができ、そのコードに関するいくつか他のもの:

  1. あなたはいつもCourseを返しています、例外が発生した場合でもベストプラクティスは、例外を呼び出し側に伝播させることです。 2番目にベストプラクティスは、nullなど、エラーが発生したことを呼び出し元に何らかのフラグを戻すことです。

  2. 文がそのコードを作ることができるのtry-で、リソースの両方短いと明確

  3. あなたはgetConnectionまたはprepareStatementの戻り値をキャストする必要はありません。

  4. あなたはwhileを使用していますが、1つの結果しか期待していません。 ifが理にかなっています。

  5. このトピックでは、ドライバにsetMaxRowsを使用してヒントを与えることができます。

  6. あなたの方法は、それがSQLExceptionを投げることができることを宣言し、それがcloseを呼び出すので、文字通り真であるが、唯一の便利SQLException実際、キャッチログイン、およびコードによって抑制、方法aの上にそれを宣言することされています少し誤解を招く。

  7. 現代のJDBCドライバでは、もうregisterDriverコールは必要ないと言われています。 (私は個人的にJDBCをしばらく使用していませんでした...)

ここでは、上記を埋める例を示します。例外が伝播することができるので、のエラー(例外条件)は通常のコードフローでは処理されません。おそらくさらに向上させることができる

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 

が、あなたのアイデアを得る:そこには、一致するコースだしない場合には、nullを返します。

+1

魔法のように働いていました。ありがとう。 – Zeus

+0

@ゼウス:心配はいりません。私は答えの最後にメモを追加しましたが、役に立つかもしれません。リソースの試行にはJDK 7以上が必要です。 –

+0

Eclipseで作業するためのリソースを試してみることはできません。このコードははるかに優れています。 – Zeus

関連する問題