我创建了一个静态方法来执行如下所示的查询
(这是在ServerProcess类中)
public static ResultSet insertRow(Connection conn, String query){
PreparedStatement pstmt = conn.prepareStatement(query);
ResultSet rs = pstmt.executeQuery();
pstmt.close();
return rs;
}
并试图获得&使用此处的结果集
ResultSet rs = ServerProcess.insertRow(conn, query)
while(rs.next()){
String nameOfEachOne = rs.getString("MEMBER_NAME");
System.out.println(nameOfEachOne);
}
但是,据我所知,一旦声明(或预备声明)关闭,结果集必然会因为连锁结果而被关闭。
我想以某种方式以这种方式使用它,但我无法弄清楚如何做到这一点。在声明结束后是否有任何可能的方法来获取信息?
答案 0 :(得分:1)
不,当父级PreparedStatement已经关闭时,您无法接收ResultSet或从中读取任何内容。
您可以做的是在关闭PreparedStatement之前使用读取ResultSet的Consumer,然后返回您需要的任何Business-Object:
消费者界面:
@FunctionalInterface
public interface SQLConsumer<T extends ResultSet, E>// where E is going to be your Business-Object Type
{
E accept(T resultSet) throws IOException;
}
Method现在返回解析器返回的内容,但正确关闭所有内容:
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;
}
解析结果:
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;
}
答案 1 :(得分:1)
理想情况下,你根本不会暴露像这样的ResultSet,它是一个非常可变/陈述的对象。但是,如果您想提供它并仍然关闭它,您可以通过lambda函数使用它:
@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
});
当然,你可以制作这样的各种方法,I've actually done abstraction就像我自己一样,用于不同RDBMS的个人项目。
答案 2 :(得分:0)
您可以使用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
有两个优点