I try to make 2 queries from a Firebird 2.5 DB. I use two separate Statement objects, but when in second query program try to use data from first query, it gets an error:
java.sql.SQLException: The result set is closed.
conn = DriverManager.getConnection(
strURL,
strUser, strPassword);
if (conn == null) {
System.err.println("Could not connect to database");
}
Statement stmt = conn.createStatement();
Statement statement = conn.createStatement();
ResultSet rs = stmt.executeQuery(strSQL);
ResultSet rs2 = null;
try {
while (rs.next()) {
String strSQL2 = "SELECT PATIENT_NAME_R, PATIENT_DOB, PATIENT_ID, PATIENT_SEX, PATIENT_ADDRESS_CITY, PATIENT_ADDRESS_SHF FROM PATIENTS WHERE PATIENT_UID = " + rs.getObject(1);
rs2 = statement.executeQuery(strSQL2);
try {
while (rs2.next()) {
System.out.println("СПРАВКА");
System.out.println("Ф.И.О.: " + rs2.getObject(1).toString().trim() + " Дата рождения: " + rs2.getObject(2));
System.out.println("СНИЛС: " + rs2.getObject(3));
System.out.println("Адрес: " + rs2.getObject(5) + " " + rs2.getObject(6));
System.out.println("Врач: " + rs.getString("STUDY_MD"));
System.out.println("----------------------------------------------------------------");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
In while (rs2.next())
in line System.out.println("Врач: " + rs.getString("STUDY_MD"))
, I get error
java.sql.SQLException: The result set is closed
at org.firebirdsql.jdbc.AbstractResultSet.checkOpen(AbstractResultSet.java:297)
at org.firebirdsql.jdbc.AbstractResultSet.getField(AbstractResultSet.java:788)
at org.firebirdsql.jdbc.AbstractResultSet.getString(AbstractResultSet.java:844)
at sample.Main$MedicalCert.run(Main.java:156)
at java.lang.Thread.run(Thread.java:748)
The problem is that you are executing two statements on a connection that is in auto-commit. In auto-commit mode, when you execute a statement, result sets created by other statements are closed.
As documented in the JDBC 4.3 specification, in section 15.2.5 Closing a ResultSet
Object:
A
ResultSet
object is implicitly closed when
- The associated
Statement
object is re-executed- The
ResultSet
is created with a Holdability ofCLOSE_CURSORS_AT_COMMIT
and an implicit or explicit commit occurs
With Jaybird (the Firebird JDBC driver), you have three options:
Disable auto-commit before executing the statements:
conn.setAutoCommit(false);
Make the first statement holdable over commit, by executing as
Statement stmt = conn.createStatement(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
This will cause the produced result set to remain open after the (automatic) commit. Be aware though, that in this mode, Jaybird will fetch the entire result set in memory, instead of fetching it in batches.
defaultResultSetHoldable
set. See also Default holdable result sets. Setting this property will affect all statements and result sets.The first option is preferable.
As an aside, I highly recommend you start using try-with-resources: your current code is vulnerable to resource leaks.
As indicated in the comments by Kayaman, you should consider rewriting your queries so it is just a single query. You are currently creating what is known as the N+1 query problem (executing a statement, and then for each row of that statement, executing another statement). Using a join in your query would allow you to execute it as a single query. And as a warning, your query is vulnerable to stored SQL injection because you concatenate a value into the query string.