1

結果セットの開始前に例外が発生したというエラーが表示されます。値 (MySQL データベースからのスコア) を取得し、プレーヤーのスコアに基づいて Java ランクに 1 つ追加しようとしています。これは、スコアボードを作成することです。

そのため、プレーヤーのスコアが現在のスコアよりも低い場合、ランク 1 で投稿されます。それより高い場合、プログラムはスコアを MySQL データベースの次のエントリと照合します。現在のすべてのエントリのランクを 1 ずつインクリメントする機能をまだ実装していません。

結論: MySQL と Java を使用してスコアボードを作成しています。Java プログラムは、入力に基づいてスコア エントリを作成し、それを MySQL データベースに送信します。

      System.out.println("Your score is: "+score*2+"  (A lower score is better.)");
      try {
   // create a java mysql database connection
   String myDriver = "com.mysql.jdbc.Driver";
   String myUrl = "jdbc:mysql://4.30.110.246:3306/apesbridge2013";
   String dbName = "apesbridge2013";
   String tbName = period + "period";
   Class.forName(myDriver);
   Connection conn = DriverManager.getConnection(myUrl, "user", CENSORED);
   next = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
   ResultSet resultSet = next.executeQuery("SELECT * FROM " + tbName);
   int cscore = resultSet.getInt("score");
   for(int sscore = score; sscore > cscore;){
       resultSet.next();
       cscore = resultSet.getInt("score");
       rank++;
   }

   stmt = conn.createStatement();
   stmt.executeUpdate("insert into " + dbName + "." + tbName + " " + "values(" + rank + ", '" + name + "', " + score + ")");
   stmt.close();
   conn.close();
 }
 catch (Exception e)
 {
   System.err.println("Got an exception! ");
   System.err.println(e.getMessage());
 }

    }
4

3 に答える 3

3

executeQueryresultSet.next();行のすぐ下に配置します。

于 2013-01-18T20:11:37.980 に答える
3

ResultSet.next()@hd1 で述べたように、次の呼び出しの後に呼び出す必要がありますexecuteQuery

while (resultSet.next()) {
...

また、SQL インジェクション攻撃から保護するには、PreparedStatement代わりにパラメーター プレースホルダーを使用することをお勧めします。java.sql.Statement

于 2013-01-18T20:15:36.730 に答える
1

for ループに問題があります。終了条件は、フェッチする行がなくなったときでなければなりません。クエリは、終了条件が満たされることを保証するものではなく、結果セットの最後を超えてフェッチしようとする可能性があります。(そして、for ループがたまたま入った場合でも、for ループがたまたま終了した場合でも、そのループによって導出されたランク値は非決定論的であり、データベースによって行が返される順序に依存します。

また、resultSet.close() または next.close() への呼び出しも表示されません。

ここには非常に多くの問題があり、どこから始めればよいかわかりません。


しかし、まず、クエリを使用してデータベースにランクを返すようにする方がはるかに効率的です。

"SELECT COUNT(1) AS rank FROM " + tbName + " WHERE score < " + score 

すべての行を引き戻して各スコアを比較するのではなく、それはただの苦痛であり、ただのノイズである大量のコードです。これにより、必要なコードに集中することができます。

それが機能するようになったら、ステートメントが SQL インジェクションに対して脆弱ではないことを確認する必要があります。バインド変数を使用する準備済みステートメントは、実際にそこに行く方法です。

close()また、結果セット、準備済みステートメント、および接続のメソッドに対する呼び出しが確実に行われるようにする必要があります。通常、これらはfinallyブロックで必要です。次のように、変数がすぐに初期化されるネストされた try/catch ブロックを使用します。

try {
    Connection conn = DriverManager.getConnection(...

    try {
        stmt = conn.CreateStatement();

        String query = "SELECT COUNT(1) AS `rank` FROM " + tbName + " WHERE `score` < " + score ;

        try {
            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {
               rank = rs.getInt("rank");
            }
        } finally {
            if (rs!=null) { rs.close() };
        }
    } finally {
        if (stmt!=null) { stmt.close() };
    }
} finally {
  if (conn!=null) { conn.close() };
}

または、1 つの大きな try/catch ブロックも実行できます。

} finally {
   if (resultSet!=null) { resultSet.close() };
   if (next!=null) { next.close() };
   if (conn!=null) { conn.close() };
)

要点は、close メソッドは実際に呼び出す必要があるということです。

于 2013-01-18T20:42:43.733 に答える