(JAVA/SQL) ResultSet 只从 MySQL 中检索一行,而它应该检索更多行

(JAVA/SQL) ResultSet only retrieving one row from MySQL when it should retrieve more

我在 Java servlet 中从 MySQL 数据库检索数据时遇到了一些问题。作为参考,我的 Web 应用程序的构造就像一个图书馆 - 您可以签出项目,然后重新签入。

当您第一次点击 "check out" 时,您的请求将发送给管理员,我们称此人为图书管理员,他必须批准或不批准您的请求。假设我登录,挑选一些物品,然后点击 "checkout"。事情是这样的:

  1. 项目已添加到我的 "cart"
  2. 在数据库的项目主列表中,每个项目都有一个名为 STATUSVARCHAR,用于标识该项目是否为 "In Stock"。对于我选择的每个项目,该变量都会更改为与我的用户帐户关联的唯一标识符。
  3. 我的请求被添加到名为 requests_list
  4. 的 table

批准、一般签到等工作正常。单击 "disapprove" 效果不佳。这是应该发生的事情:

  1. 请求已从 requests_list
  2. 中删除
  3. 请求者的 "cart" 项目被截断
  4. 项目本身得到声明"In Stock"

这是正在发生的事情:

  1. 请求已从 requests_list
  2. 中删除
  3. 请求者的 "cart" 项目被截断
  4. 只有购物车中的第一件商品会被重新签入

这是我目前使用的代码:

stmt.execute("DELETE FROM requests_list WHERE UNIQUE_ID = '"
                        + selected_ID + "'"); // this seems to work

stmt.execute("TRUNCATE TABLE checkout_" + selected_ID); // also seems to work

ResultSet all_gear = stmt
                        .executeQuery("SELECT * FROM gear_master_list");

while (all_gear.next()) {
    if (all_gear.getString(5).equals(selected_ID)) {
        stmt.execute("UPDATE gear_master_list SET STATUS = 'In Stock' WHERE ID_NUM = "
                                + all_gear.getInt(6));
    }
}

all_gear.close();

一些注释,用于解释一些变量:

我尝试过不同的做法,这样代码会遍历购物车中的所有商品,更新状态,然后截断 table。这也没有用 - 它对更新状态仍然很挑剔,而且 table 不会截断。

TL;DR: 即使我使用while 循环,不止一行。这是怎么回事?有没有更好、更有效的方法来做到这一点?

这可能是一个并发修改问题 - 您的第一个查询在数据库上保持打开的游标,并且在遍历该游标时您正在对相同的数据执行更新,所有这些都在同一事务中。

你能试试这个吗?

    stmt.execute("DELETE FROM requests_list WHERE UNIQUE_ID = '"
            + selected_ID + "'"); // this seems to work

    stmt.execute("TRUNCATE TABLE checkout_" + selected_ID); // also seems to
                                                            // work

    ResultSet all_gear = stmt
            .executeQuery("SELECT * FROM gear_master_list");

    List<String> gear_items = new ArrayList<>();
    while (all_gear.next()) {
        gear_items.add(all_gear.getString(5));
    }
    all_gear.close();

    for (String gear_item: gear_items){
        if (all_gear.getString(5).equals(selected_ID)) {
            stmt.execute("UPDATE gear_master_list SET STATUS = 'In Stock' WHERE ID_NUM = "
                    + all_gear.getInt(6));
        }
    }

    stmt.close();

非常感谢 hugh 对这个问题的大力帮助 - 他的回答是正确的。我只需要做一些修改来帮助他的响应适合我的代码。

以防其他人遇到这个问题,Hugh 是对的,这是一个 并发修改 问题。但是,他的回复中有一个轻微的错字(ResultSet 在某些语句被调用之前关闭),所以我想我会 post 我修改的代码以防万一它对任何人都有帮助:

stmt.execute("DELETE FROM requests_list WHERE UNIQUE_ID = '" + selected_ID + "'"); // this seems to work

stmt.execute("TRUNCATE TABLE checkout_" + selected_ID); // also seems to work

ResultSet all_gear = stmt.executeQuery("SELECT * FROM gear_master_list");

ArrayList<Object[]> gear_items = new ArrayList<Object[]>();
while (all_gear.next()) {
    Object[] added = new Object[2];
    added[0] = all_gear.getString(5);
    added[1] = all_gear.getInt(6);
    gear_items.add(added);
}
all_gear.close();

for (Object[] gear_item : gear_items) {
    if (gear_item[0].equals(selected_ID)) {
        stmt.execute("UPDATE gear_master_list SET STATUS = 'In Stock' WHERE ID_NUM = " + gear_item[1]);
    }
}

stmt.close();

// thanks again to hugh!