Reputation: 33
I made a static method for executing the queries like this below
(this is in ServerProcess class)
public static ResultSet insertRow(Connection conn, String query){
PreparedStatement pstmt = conn.prepareStatement(query);
ResultSet rs = pstmt.executeQuery();
pstmt.close();
return rs;
}
and trying to get & use the resultset from here
ResultSet rs = ServerProcess.insertRow(conn, query)
while(rs.next()){
String nameOfEachOne = rs.getString("MEMBER_NAME");
System.out.println(nameOfEachOne);
}
But, as far as I know, once statement(or preparedstatement) closed, resultset would be bound to get closed as a knock-on consequences.
I would like to use it in this way somehow, but I can't figure out how to do it. Is there any possible ways to get information set after the statement closed ?
Upvotes: 3
Views: 1706
Reputation: 11
You can use CachedRowSet
.
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet rowset = factory.createCachedRowSet();
rowset .setUsername(username);
rowset .setPassword(password);
rowset .setUrl("jdbc:mySubprotocol:mySubname"); // or setDataSource()
rowset .setCommand("select * from table");
rowset.execute(); // now you have populate data
There are two advantages
Upvotes: 0
Reputation: 2386
No, you can't receive the ResultSet or read anything from it when the parent PreparedStatement is already closed.
What you can do is to work with a Consumer which reads the ResultSet before you close the PreparedStatement and then returns any Business-Object you need:
The Consumer-Interface:
@FunctionalInterface
public interface SQLConsumer<T extends ResultSet, E>// where E is going to be your Business-Object Type
{
E accept(T resultSet) throws IOException;
}
The Method now returns what the parser returns, but closes everything properly:
public static <E> E insertRow(Connection conn, String query, SQLConsumer<? super ResultSet, ? extends E> parser)
{
E result;
// use the try-with-resources functionality
try (PreparedStatement pstmt = conn.prepareStatement(query)
; ResultSet rs = pstmt.executeQuery())
{
// give the ResultSet to the parser to process it before closing the PreparedStatement
result = parser.accept(rs);
}
return result;
}
And parsing the result:
public void callingMethod()
{
ArrayList<String> result = insertRow(conn, "MY_QUERY", this::parseResultSet);
}
private ArrayList<String> parseResultSet(ResultSet resultSet) throws IOException
{
ArrayList<String> values = new ArrayList<>();
while (resultSet.next())
{
values.add(resultSet.getString("MEMBER_NAME"));
}
return values;
}
Upvotes: 1
Reputation: 11483
Ideally you would never expose a ResultSet like that at all, it's a very mutable/stated object. However if you want to provide it, and still close it, you can use it via a lambda function:
@FunctionalInterface interface SQLConsumer<T> {
public void accept(T t) throws SQLException; //default functional interfaces can't throw
}
public void query(String sql, SQLConsumer<? super ResultSet> action) {
ResultSet rs = /* various jdbc code */;
action.accept(rs);
rs.close(); //and other resources
}
//In usage:
query("SELECT * FROM my_table", rs -> {
String s = rs.getString(1); //example
});
Of course, you can make various methods like this, and I've actually done abstraction like that myself for personal projects across different RDBMSes.
Upvotes: 1