1

在以下代码中,我通过以下executeRestitutionalQuery(String query)方法对 SQLite JDBC 连接执行查询:

public static ArrayList<Metadata> findMetadata(String name, String text, String after, String before, String repPath)
    throws SQLException, ClassNotFoundException {

    ArrayList<Metadata> data = new ArrayList<Metadata>();
    boolean needADD = false;

    String query = "SELECT * from " + TABLE_NAME_METADATA;

    ...

    query += " ORDER BY timestamp DESC;";

    ResultBundle bundle = executeRestitutionalQuery(query);
    ResultSet result = bundle.getResultSet();

    while(result.next()){
        Metadata metadata = new Metadata(result.getLong("id"), result.getString("name"), Timestamp.valueOf(result.getString("timestamp")), 
                result.getInt("filesNo"), result.getLong("size"), result.getString("description"), -1);
        data.add(metadata);
    }

    closeStatementAndResultSet(bundle.getStatement(), bundle.getResultSet());

    return data;
}

private static ResultBundle executeRestitutionalQuery(String query) throws SQLException, ClassNotFoundException{

    Connection connection = null;
    Statement statement = null;
    ResultSet result = null;
    ResultBundle bundle = null;

    try{
        connection = getConnection();
        statement = connection.createStatement();
        statement.executeUpdate(query);
        connection.commit();

        result = statement.executeQuery(query);

        bundle = new ResultBundle(statement, result);

    }finally{

        if(connection != null){
            try{
                connection.close();
            }catch (Exception e){
                /* ignored */
            }
        }
    }

    return bundle;
}
private static void closeStatementAndResultSet(Statement statement, ResultSet result){
    if(result != null){
        try{
            result.close();
        }catch (Exception e){
            // ignored
        }
    }

    if(statement != null){
        try{
            statement.close();
        }catch (Exception e){
            // ignored
        }
    }
}

该类ResultBundle仅用于汇总结果集和语句。它看起来像这样:

public class ResultBundle {

private final Statement statement;
private final ResultSet result;

public ResultBundle(Statement statement, ResultSet result){
    this.result = result;
    this.statement = statement;
}

public Statement getStatement(){
    return statement;
}

public ResultSet getResultSet(){
    return result;
}

}

问题是,每次调用result.getLong()result.getString()都会返回null相应的。0. 我不明白为什么。查询应该没问题,因为在我不得不进行一些重构之前代码运行良好。问题可能来自ResultBundle-class吗?我在这里没有看到什么?

4

2 回答 2

4

Statements 和ResultSets 是“活”的对象,只要它们的连接就可以存活。executeRestitutionalQuery返回 a ,当在块中关闭连接时ResultBundle,其resultstatement成员在返回时隐式关闭。finally

try {

    ...

}finally{

    if(connection != null){
         try{
             connection.close();      // <---- here's the problem
         }catch (Exception e){
             /* ignored */
         }
     }
 }

此时,调用者executeRestitutionalQuerycan 把手放在资源包上,连接已关闭,结果集“死”。

于 2013-10-18T20:40:56.003 回答
2

我会说这是一个糟糕的设计。

更好的方法是将 SQL 对象保持在严格的范围内,将结果映射到集合或对象中,并立即关闭所有这些稀缺资源。数据不仅可供客户端使用,而且您还可以避免连接和游标耗尽等令人讨厌的问题。它也会更好地扩展。

于 2013-10-18T21:03:14.820 回答