JDBC-ResultSet在while-Loop中关闭

我在使用ResultSet时遇到了非常糟糕的时间,ResultSet在while-Loop中关闭,用于迭代此ResultSet。 我已经知道ResultSet关闭的确切行,但我不知道为什么。

public LinkedList alleAbrufen () throws SQLException { LinkedList alleAthleten = new LinkedList(); String abrufenAthleten = "SELECT * FROM Athlet ORDER BY athlet_id"; ResultSet athleten_rs = stmt.executeQuery(abrufenAthleten); while (athleten_rs.next()) { long id = athleten_rs.getInt(1); String name = athleten_rs.getString(2); LinkedList alleLeistungen = alleAbrufen((int) (id)); //after this line the ResultSet gets closed alleAthleten.add(new Athlet(id, name, alleLeistungen)); } return alleAthleten; } public LinkedList alleAbrufen(int athlet_id) throws SQLException { LinkedList alleLeistungen = new LinkedList(); String selectLeistungen = "SELECT * FROM Leistung WHERE athlet_id="+athlet_id; ResultSet rs = stmt.executeQuery(selectLeistungen); while (rs.next()) { long id = rs.getInt(1); String bezeichnung = rs.getString(2); String datum = rs.getString(3); double geschwindigkeit = rs.getDouble(4); boolean selectedForSlopeFaktor = rs.getBoolean(5); int strecke_id = rs.getInt(7); long longAthlet_id = (long) athlet_id; Leistung leistung = new Leistung(strecke_id, longAthlet_id, bezeichnung, datum, geschwindigkeit); leistung.setLeistungID(id); leistung.setIsUsedForSlopeFaktor(selectedForSlopeFaktor); alleLeistungen.add(leistung); } return alleLeistungen; } 

我标记了一行,之后用注释关闭了ResultSet 。 在上面的例子中使用的其他方法,构造函数等都经过了正确的测试。 有没有人知道为什么调用第二个方法在第一个方法中关闭ResultSet

问题是Statement只能为每个执行的语句维护一组ResultSet 。 由于您为两个方法共享相同的Statement stmt ,因此在alleAbrufenStatement执行另一个语句,该语句将中断对先前ResultSet的引用。

这种情况的最佳解决方案是创建Statement per statement执行。 也就是说,每个方法都应包含其唯一的Statement和相关的ResultSet

 public LinkedList alleAbrufen () throws SQLException { LinkedList alleAthleten = new LinkedList(); String abrufenAthleten = "SELECT * FROM Athlet ORDER BY athlet_id"; //here Statement stmtAlleAbrufen = con.createStatement(); ResultSet athleten_rs = stmtAlleAbrufen.executeQuery(abrufenAthleten); while (athleten_rs.next()) { long id = athleten_rs.getInt(1); String name = athleten_rs.getString(2); LinkedList alleLeistungen = alleAbrufen((int) (id)); //after this line the ResultSet gets closed alleAthleten.add(new Athlet(id, name, alleLeistungen)); } return alleAthleten; } public LinkedList alleAbrufen(int athlet_id) throws SQLException { LinkedList alleLeistungen = new LinkedList(); //here again, but since you need to use parameters in your query //use PreparedStatement instead //note that I commented the current query //String selectLeistungen = "SELECT * FROM Leistung WHERE athlet_id="+athlet_id; //this is how a query with parameters look like String selectLeistungen = "SELECT * FROM Leistung WHERE athlet_id=?"; //the connection prepares the statement PreparedStatement pstmt = con.prepareStatement(selectLeistungen); //then we pass the parameters pstmt.setInt(1, athlet_id); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { long id = rs.getInt(1); String bezeichnung = rs.getString(2); String datum = rs.getString(3); double geschwindigkeit = rs.getDouble(4); boolean selectedForSlopeFaktor = rs.getBoolean(5); int strecke_id = rs.getInt(7); long longAthlet_id = (long) athlet_id; Leistung leistung = new Leistung(strecke_id, longAthlet_id, bezeichnung, datum, geschwindigkeit); leistung.setLeistungID(id); leistung.setIsUsedForSlopeFaktor(selectedForSlopeFaktor); alleLeistungen.add(leistung); } return alleLeistungen; } 

在使用它们之后,不要忘记关闭资源StatementResultSet

你的问题的答案来自javadoc:

默认情况下,每个Statement对象只能同时打开一个ResultSet对象。 因此,如果读取一个ResultSet对象与另一个ResultSet对象的读取交错,则每个ResultSet对象必须由不同的Statement对象生成。

您的Statement是一个类变量,并且您对这两个查询使用相同的变量吗? 是的,这是错的。 每个Statement只能有一个ResultSet

请参阅java文档 。