Java 在执行CallableStatement之前,无法从该语句检索结果

Java 在执行CallableStatement之前,无法从该语句检索结果,java,postgresql,stored-procedures,jdbc,callable-statement,Java,Postgresql,Stored Procedures,Jdbc,Callable Statement,我在应用程序中使用此方法来获取特定组织的子组织。它调用一个存储过程(创建一个临时表) StoredProcedureDAO.java private Connection dbConnection = null; private CallableStatement cstmt = null; private ResultSet results = null; 内部getChildrens(int siteId)方法 public ArrayList<String> getChild

我在应用程序中使用此方法来获取特定组织的子组织。它调用一个存储过程(创建一个临时表)

StoredProcedureDAO.java

private Connection dbConnection = null;
private CallableStatement cstmt = null;
private ResultSet results = null;
内部getChildrens(int siteId)方法

public ArrayList<String> getChildrens(int siteId)
{
    ArrayList<String> childrenSites = new ArrayList<String>();
    Connection pgConnection = getFreshDBConnection();
    if (pgConnection == null) {
        cat.error("getChildrens got a null connection");
        return null;
    }
    try{            
        pgConnection.setAutoCommit(false);
        cstmt = pgConnection.prepareCall("{ ? = call \"spGetChildSitesInfo\" ( ? ) }");
        cstmt.registerOutParameter(1, Types.OTHER);
        cstmt.setInt(2, siteId);
        cstmt.execute();
        results = (ResultSet) cstmt.getObject(1);
        if(results != null){
            while(results.next()){
                childrenSites.add(results.getString(1));
            }
        }
        cstmt.close();
        pgConnection.commit();
        pgConnection.close();
    } catch (SQLException e){
        try {
            pgConnection.rollback();
            cat.error("SQL Exception has occured while retriving the children", e);
        } catch (Exception ex) {
            cat.error("Error while connection rollback: ", e);
        }

    } finally {
        try {
            if(!pgConnection.isClosed()){
                pgConnection.setAutoCommit(true);
                pgConnection.close();
            }
            pgConnection = null;
        } catch (Exception e) {
            cat.error("Error while closing the connection: "+e);
        }
    }

    return childrenSites;
}
在实验后添加更多信息

这是我的构造函数(私有)

下面是getInstance()

我使用以下命令调用getChildrens()

StoredProcedureDAO dao = StoredProcedureDAO.getInstance();
children = dao.getChildrens(site_id);
现在,如果我删除if语句

//if (myself == null)
在这种情况下,我没有得到例外。

我正在使用postgresql-9.0-801.jdbc4.jar驱动程序。谁能解释一下原因吗?

您遇到了多线程问题。看起来您正在不同线程之间共享ResultSet成员变量(servlet(或JSP)可以由多个线程共享),因此出现了错误。您确定要创建多个
StoredProcedureDAO
实例吗?

您有多线程问题。看起来您正在不同线程之间共享ResultSet成员变量(servlet(或JSP)可以由多个线程共享),因此出现了错误。确实要创建多个实例吗?

您应该在finally中关闭结果。您可以尝试。

您应该在finally中关闭结果。您可以尝试。

问题是跨线程共享非线程安全资源。停止尝试手动管理所有数据库资源,让Spring为您处理所有这些资源。这将使您免于陷入困境。

问题在于跨线程共享非线程安全的资源。停止尝试手动管理所有数据库资源,让Spring为您处理所有这些资源。这将使您免于陷入困境。

pgConnection在哪里打开?示例代码中它正在关闭,这可能是第二次单击出现问题的原因。@g051051我已经编辑了我的问题,以显示连接打开的位置。pgConnection在哪里打开?示例代码中正在关闭该问题,这可能是第二次单击出现问题的原因。@g051051我已编辑了我的问题,以显示连接在何处打开Hanks ivy。很明显,问题出在线程上。有时我会变得如此愚蠢。我用一些附加信息编辑了这个问题。你能编辑你的答案解释我的原因吗;使用Spring这样的框架在web上下文中处理DAO的线程安全注入是明智的。您的单例
getInstance()
应该同步以确保安全,但真正的问题在于
ResultSet results
是DAO的成员。您仍然在跨线程共享这个DAO实例(与resultSet成员),并且每个实例都在覆盖resultSet。resultSet应该是线程的局部变量!谢谢艾薇。很明显,问题出在线程上。有时我会变得如此愚蠢。我用一些附加信息编辑了这个问题。你能编辑你的答案解释我的原因吗;使用Spring这样的框架在web上下文中处理DAO的线程安全注入是明智的。您的单例
getInstance()
应该同步以确保安全,但真正的问题在于
ResultSet results
是DAO的成员。您仍然在跨线程共享这个DAO实例(与resultSet成员),并且每个实例都在覆盖resultSet。resultSet应该是线程的局部变量!事实上,这是一个旧的应用程序,我正在尝试修复当前的错误,所以我不能改变整个设计。关于使用更好的框架,您是对的。我正在使用spring开发另一个应用程序,它非常好technology@anu:我不是说完全改变应用程序的基础结构。只需创建一个JdbcTemplate并使用它的方法。这是一个旧的应用程序,我正在尝试修复当前的bug,所以我不能改变整个设计。关于使用更好的框架,您是对的。我正在使用spring开发另一个应用程序,它非常好technology@anu:我不是说完全改变应用程序的基础结构。只需创建一个JdbcTemplate并使用它的方法。它将为您管理所有的资源。它一开始就不起作用。你可以阅读我编辑的问题。无论如何,它一开始就不起作用。你可以阅读我编辑的问题。反正是tnx
public static StoredProcedureDAO getInstance()
    {
        if (myself == null)
            myself = new StoredProcedureDAO();
        return myself;
    }
StoredProcedureDAO dao = StoredProcedureDAO.getInstance();
children = dao.getChildrens(site_id);
//if (myself == null)