1

我收到一条错误消息,指出在结果集开始之前我遇到了异常。我正在尝试获取一个值(来自 MySQL 数据库的分数)并根据玩家分数将一个值添加到 Java 排名中。这是为了创建一个记分牌。

因此,如果玩家的分数低于当前分数,则以排名 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

放在resultSet.next();您的 executeQuery 行的正下方。

于 2013-01-18T20:11:37.980 回答
3

正如@hd1 所述,您需要在调用ResultSet.next()后调用executeQuery

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

此外,更好地使用PreparedStatement而不是java.sql.Statement使用参数占位符来防止SQL 注入攻击:

于 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() };
}

或者一个大的 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 回答