I've created a method to fetch details from Database which returns an object of ResultSet by executing a callableStatement. I want to close the Connection & CallableStatement. For performing this I'm using try-with-resource. But the problem arise here, as I'm return the ResultSet from my method, it also gets closed and throws an exception while fetching data from it:
com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed.
As per my knowledge, ResultSet will automatically get closed when either all data is fetched from ResultSet or if the CallableStatement will get closed. In my case second thing is happening as I'm using try-with-resource.
This is how my code looks like.
public ResultSet getUSStates() throws SQLException {
try(
Connection inGlobalConnnections = getConnection();
CallableStatement csmt = inGlobalConnnections.prepareCall("{call mst.USP_GetUSStates()}");) {
csmt.execute();
return csmt.getResultSet();
} catch (Exception e) {
_log.error(e, e);
}
return null;
}
What should I do to fetch records and close the connections afterwards?
NOTE: I'm using multiple methods like this to fetch details from database. So, please suggest way where I have to perform minimal changes in my code.
As the comments suggest, a
ResultSetshould generally be processed immediately, not handed off.I suggest either:
ResultSetinto aRowSet.javax.sql.RowSetInstead, use the sub-interface of
ResultSetthat is meant for handing off data directly from the database:RowSet. In your case,CachedRowSetsounds appropriate.See tutorial by Oracle. And see article by Michael Good on Baeldung.
The catch is finding a concrete implementation of that interface. You may find one bundled with JDKs based on OpenJDK. But as I recall, that implementation is very old (like dating back to the Sun Microsystems days), and has not been maintained/updated.
Row sets always seemed like a great idea to me. But apparently they have never received the attention they deserve.
For more on obtaining implementations of
RowSet, see these Questions: here and here.Here is a full example app, using H2 Database Engine.
Notice how, in modern Java,
RowSetProvideruses the Java Service Provider Interface (SPI) to locate and load an implementation at runtime. (Well, I think that is what’s going on here.) See: What the reason to use RowSetProvider to obtain RowSetFactory?.When run:
recordOr cache the data yourself by writing a
recordclass, populate a collection of those objects from yourResultSet, and hand off the collection.