使用 executeUpdate 的 ResultSet 出现问题
Trouble with ResultSet using executeUpdate
我是编程新手,在将 executeUpdate 与 resultSet next() 方法结合使用时遇到了 运行 问题。
它仅遍历结果集一次,然后执行更新关闭结果集。我得到错误:结果集未打开。不允许操作 "next"。确认自动提交已关闭。
我添加了 con.setAutoCommit(false) 语句,但问题仍然存在。
我需要 运行 使用不同的变量值多次更新。
这是我的代码:
try {
String eidQuery = "SELECT EID FROM EMPLOYEE_DATA WHERE ACTIVE = TRUE ORDER BY EID";
int nextEID;
Statement st = con.createStatement();
con.setAutoCommit(false);
rs = st.executeQuery(eidQuery);
while (rs.next()){
nextEID = rs.getInt(1);
String getDailyTotals = "SELECT DATE, SUM(TOTAL), MAX(OUT_1) FROM PUNCHES WHERE EID = " + nextEID + " AND DATE >= '" + fd + "' "
+ "AND DATE <= '" + td + "' GROUP BY DATE";
ResultSet rs2 = st.executeQuery(getDailyTotals);
while (rs2.next()){
double dailyTotal = rs2.getDouble(2);
if (dailyTotal > 8){
double dailyOT = dailyTotal-8;
String dailyDate = rs2.getDate(1).toString();
Timestamp maxTime = rs2.getTimestamp(3);
String updateOT = "UPDATE PUNCHES SET OT = " + dailyOT + " WHERE EID = " + nextEID + " AND DATE = '" + dailyDate + "' AND OUT_1 = '" + maxTime + "'";
st.executeUpdate(updateOT);
}
}
}
rs = st.executeQuery("SELECT PUNCHES.EID, EMPLOYEE_DATA.FIRST_NAME, EMPLOYEE_DATA.LAST_NAME, SUM(PUNCHES.OT) FROM PUNCHES "
+ "JOIN EMPLOYEE_DATA ON PUNCHES.EID = EMPLOYEE_DATA.EID WHERE PUNCHES.DATE >= '" + fd + "' AND PUNCHES.DATE <= '" + td + "' GROUP BY EMPLOYEE_DATA.FIRST_NAME, EMPLOYEE_DATA.LAST_NAME, PUNCHES.EID");
Reports.setModel(DbUtils.resultSetToTableModel(rs));
} catch (SQLException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(null, ex);
}
您是编程新手并且(显然)Java。以下是我可以为您提供的一些建议:
- 帮自己一个忙,了解一下
PreparedStatement
。您不应该通过连接 Strings
. 来创建 SQL
- 您正在犯下将数据库和 UI Swing 代码混合到一个难以调试的块中的经典新手错误。最好将您的应用程序分解为多个层。从封装所有数据库代码的数据访问接口开始。进行测试并为您的 UI 提供一个实例。
- 不要在 ResultSet 的循环中插入更新查询。最好把两者完全分开。
- 了解 MVC。您会希望您的 Swing View 与应用程序控制器分开。让Controller与数据访问接口进行交互,获取结果,并将结果交给View进行显示。保持它们解耦和分离。
- 学习JUnit。它将帮助您进行测试。
来自 java.sql.ResultSet javadoc:
A ResultSet object is automatically closed when the Statement object
that generated it is closed, re-executed, or used to retrieve the next
result from a sequence of multiple results.
执行更新后,关闭先前的ResultSet。您需要重新编写代码来解决这个问题。
https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
最简单的返工方法可能是使用两个语句,一个用于查询,一个用于更新,但正如 duffymo 的回答中所述,您可以做更多的事情来改进。
来自API的声明文档"By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects"
如果你想在同一个嵌套循环中读取两个不同的结果集,你需要两个不同的语句。
我是编程新手,在将 executeUpdate 与 resultSet next() 方法结合使用时遇到了 运行 问题。 它仅遍历结果集一次,然后执行更新关闭结果集。我得到错误:结果集未打开。不允许操作 "next"。确认自动提交已关闭。 我添加了 con.setAutoCommit(false) 语句,但问题仍然存在。 我需要 运行 使用不同的变量值多次更新。 这是我的代码:
try {
String eidQuery = "SELECT EID FROM EMPLOYEE_DATA WHERE ACTIVE = TRUE ORDER BY EID";
int nextEID;
Statement st = con.createStatement();
con.setAutoCommit(false);
rs = st.executeQuery(eidQuery);
while (rs.next()){
nextEID = rs.getInt(1);
String getDailyTotals = "SELECT DATE, SUM(TOTAL), MAX(OUT_1) FROM PUNCHES WHERE EID = " + nextEID + " AND DATE >= '" + fd + "' "
+ "AND DATE <= '" + td + "' GROUP BY DATE";
ResultSet rs2 = st.executeQuery(getDailyTotals);
while (rs2.next()){
double dailyTotal = rs2.getDouble(2);
if (dailyTotal > 8){
double dailyOT = dailyTotal-8;
String dailyDate = rs2.getDate(1).toString();
Timestamp maxTime = rs2.getTimestamp(3);
String updateOT = "UPDATE PUNCHES SET OT = " + dailyOT + " WHERE EID = " + nextEID + " AND DATE = '" + dailyDate + "' AND OUT_1 = '" + maxTime + "'";
st.executeUpdate(updateOT);
}
}
}
rs = st.executeQuery("SELECT PUNCHES.EID, EMPLOYEE_DATA.FIRST_NAME, EMPLOYEE_DATA.LAST_NAME, SUM(PUNCHES.OT) FROM PUNCHES "
+ "JOIN EMPLOYEE_DATA ON PUNCHES.EID = EMPLOYEE_DATA.EID WHERE PUNCHES.DATE >= '" + fd + "' AND PUNCHES.DATE <= '" + td + "' GROUP BY EMPLOYEE_DATA.FIRST_NAME, EMPLOYEE_DATA.LAST_NAME, PUNCHES.EID");
Reports.setModel(DbUtils.resultSetToTableModel(rs));
} catch (SQLException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(null, ex);
}
您是编程新手并且(显然)Java。以下是我可以为您提供的一些建议:
- 帮自己一个忙,了解一下
PreparedStatement
。您不应该通过连接Strings
. 来创建 SQL
- 您正在犯下将数据库和 UI Swing 代码混合到一个难以调试的块中的经典新手错误。最好将您的应用程序分解为多个层。从封装所有数据库代码的数据访问接口开始。进行测试并为您的 UI 提供一个实例。
- 不要在 ResultSet 的循环中插入更新查询。最好把两者完全分开。
- 了解 MVC。您会希望您的 Swing View 与应用程序控制器分开。让Controller与数据访问接口进行交互,获取结果,并将结果交给View进行显示。保持它们解耦和分离。
- 学习JUnit。它将帮助您进行测试。
来自 java.sql.ResultSet javadoc:
A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
执行更新后,关闭先前的ResultSet。您需要重新编写代码来解决这个问题。 https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
最简单的返工方法可能是使用两个语句,一个用于查询,一个用于更新,但正如 duffymo 的回答中所述,您可以做更多的事情来改进。
来自API的声明文档"By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects"
如果你想在同一个嵌套循环中读取两个不同的结果集,你需要两个不同的语句。