在准备好的陈述结束后有没有办法获得结果集? (java)

时间:2017-06-10 04:45:42

标签: java sql prepared-statement resultset

我创建了一个静态方法来执行如下所示的查询

(这是在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);  
}

但是,据我所知,一旦声明(或预备声明)关闭,结果集必然会因为连锁结果而被关闭。

我想以某种方式以这种方式使用它,但我无法弄清楚如何做到这一点。在声明结束后是否有任何可能的方法来获取信息?

3 个答案:

答案 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

有两个优点

  1. 不需要prepareStatement
  2. 关闭连接或准备比较方法的语句没问题