通过JPA(Websphere和DB2)引用表时,结果集是关闭的错误

通过JPA(Websphere和DB2)引用表时,结果集是关闭的错误,jpa,db2,websphere,openjpa,Jpa,Db2,Websphere,Openjpa,我在WebSphere 7上使用IBM的OpenJPA实现,当我试图引用@ManyToOne对象并不断从DB2获得以下错误时,我遇到了一个问题: @SuppressWarnings("unchecked") public List<Report> getOpenIncidentsForUser(String aceId) throws Exception { List<Report> results = null; EntityManager em = g

我在WebSphere 7上使用IBM的OpenJPA实现,当我试图引用@ManyToOne对象并不断从DB2获得以下错误时,我遇到了一个问题:

@SuppressWarnings("unchecked")
public List<Report> getOpenIncidentsForUser(String aceId) throws Exception
{
    List<Report> results = null;
    EntityManager em = getEntityManager();

    try
    {
        Query query = em.createNamedQuery("getOpenIncidentsForUser");
        query.setParameter(1, aceId);
        results = (List<Report>) query.getResultList();

        Iterator<Report> it = results.iterator();
        while(it.hasNext())
        {
            Report report = it.next();
            System.out.println("Report [" + report.getRecordId() + "] Agency: [" + report.getAgency() + "]");
        }
    }
    catch (Exception e)
    {
        log.fatal("Fatal error getting incidents for user", e);
        throw e;
    }
    finally
    {
        em.close();
    }

    return (List<Report>) results;
}
com.ibm.db2.jcc.b.SqlException:[jcc][t4][10120][10898][3.50.152]无效操作:结果集已关闭。ERRORCODE=-4470,SQLSTATE=null

我正在绞尽脑汁想为什么这行不通,希望有人能帮上忙

以下是数据库架构的简化视图:

表格报告

record_id-integer-(主键-由DB2生成)

代理-整数不为空(下拉表的外键)

表格下拉列表

record_id-integer-(主键-由DB2生成)

以下是JPA实体的报告,该报告引用了该机构

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="AGENCY")
private Dropdown agency;
下面是我运行命名查询以获取数据的代码,然后迭代结果集以打印出报告id和Agency。无论何时调用report.getAgency(),我都会从DB2得到“result set is closed”错误:

@SuppressWarnings("unchecked")
public List<Report> getOpenIncidentsForUser(String aceId) throws Exception
{
    List<Report> results = null;
    EntityManager em = getEntityManager();

    try
    {
        Query query = em.createNamedQuery("getOpenIncidentsForUser");
        query.setParameter(1, aceId);
        results = (List<Report>) query.getResultList();

        Iterator<Report> it = results.iterator();
        while(it.hasNext())
        {
            Report report = it.next();
            System.out.println("Report [" + report.getRecordId() + "] Agency: [" + report.getAgency() + "]");
        }
    }
    catch (Exception e)
    {
        log.fatal("Fatal error getting incidents for user", e);
        throw e;
    }
    finally
    {
        em.close();
    }

    return (List<Report>) results;
}
@SuppressWarnings(“未选中”)
公共列表getOpenIncidentsForUser(字符串aceId)引发异常
{
列表结果=空;
EntityManager em=getEntityManager();
尝试
{
Query Query=em.createNamedQuery(“getOpenIncidentsForUser”);
query.setParameter(1,aceId);
results=(List)query.getResultList();
Iterator it=results.Iterator();
while(it.hasNext())
{
Report=it.next();
System.out.println(“Report[”+Report.getRecordId()+“]代理:[“+Report.getAgency()+”]);
}
}
捕获(例外e)
{
log.fatal(“为用户获取事件的致命错误”,e);
投掷e;
}
最后
{
em.close();
}
返回(列表)结果;
}

如果我不使用getAgency方法,我可以毫无问题地打印出关于报告的任何其他内容。这似乎只是参考了第二张表。有什么想法吗?

我在回复我最初的评论时回答了这个问题,但我意识到我从未将问题标记为已回答,所以我想正式回答

此处记录了修复程序:


修复结果是ResultSetHoldability设置需要为1而不是2

对于XA数据源,您必须将
gradeholdcursorunderxa
设置为
true
,否则您可能会收到此消息的持久性异常:

An SQL OPEN for a held cursor was issued on a XA connection

我在回应我最初的评论时回答了这个问题,但我意识到我从来没有将这个问题标记为已回答,所以我想正式地这样做

此处记录了修复程序:


修复结果是ResultSetHoldability设置需要为1而不是2

对于XA数据源,您必须将
gradeholdcursorunderxa
设置为
true
,否则您可能会收到此消息的持久性异常:

An SQL OPEN for a held cursor was issued on a XA connection

只有在使用非XA数据源时,设置DB2ResultSetTholdability=1才有效。如果你需要保持2便士,那么这不是一个解决方案

我遇到了这个确切的问题,并最终通过围绕有问题的代码对事务进行硬编码来解决它。这就是我所拥有的:

public class RequeueRuleList_back {

/*
 * Injected resources ...
 */
@Resource UserTransaction txn;
@PersistenceUnit EntityManagerFactory emf;

:

public List<RequeueRuleBean> getRequeueRules() {

    /* 
     * We need a hard transaction around this code even though it is just a query
     * otherwise we cannot use a DB2 XA datasource to do this:
     * 
     * com.ibm.db2.jcc.am.SqlException: [jcc][t4][10120][10898][3.63.75] Invalid operation: result set is closed. ERRORCODE=-4470, SQLSTATE=null
     */

    try {
        txn.begin();
    } catch (Exception e) {
        FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage("Error starting transaction: " + e.getMessage()));
        return null;
    }
    EntityManager em = emf.createEntityManager();

    :

    Query q = em.createQuery("SELECT rr FROM RequeueRule rr");

    // Do useful things ...

    em.close();
    try {
        txn.commit();
    } catch (Exception e) {
        FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage("Error committing transaction: " + e.getMessage()));
    }
    :
}
公共类重新查询列表\u返回{
/*
*注入的资源。。。
*/
@资源用户事务txn;
@持久性单位实体管理工厂emf;
:
公共列表GetRequeQueules(){
/* 
*我们需要一个围绕这段代码的硬事务,即使它只是一个查询
*否则,我们无法使用DB2 XA数据源执行此操作:
* 
*com.ibm.db2.jcc.am.SqlException:[jcc][t4][10120][10898][3.63.75]无效操作:结果集已关闭。错误代码=-4470,SQLSTATE=null
*/
试一试{
txn.begin();
}捕获(例外e){
FacesContext.getCurrentInstance().addMessage(空,
新的FacesMessage(“启动事务时出错:+e.getMessage());
返回null;
}
EntityManager em=emf.createEntityManager();
:
Query q=em.createQuery(“从重新查询rr中选择rr”);
//做有用的事情。。。
em.close();
试一试{
提交();
}捕获(例外e){
FacesContext.getCurrentInstance().addMessage(空,
新的FacesMessage(“提交事务时出错:+e.getMessage());
}
:
}

}

只有在使用非XA数据源的情况下,设置DB2 ResultsTholdability=1才有效。如果你需要保持2便士,那么这不是一个解决方案

我遇到了这个确切的问题,并最终通过围绕有问题的代码对事务进行硬编码来解决它。这就是我所拥有的:

public class RequeueRuleList_back {

/*
 * Injected resources ...
 */
@Resource UserTransaction txn;
@PersistenceUnit EntityManagerFactory emf;

:

public List<RequeueRuleBean> getRequeueRules() {

    /* 
     * We need a hard transaction around this code even though it is just a query
     * otherwise we cannot use a DB2 XA datasource to do this:
     * 
     * com.ibm.db2.jcc.am.SqlException: [jcc][t4][10120][10898][3.63.75] Invalid operation: result set is closed. ERRORCODE=-4470, SQLSTATE=null
     */

    try {
        txn.begin();
    } catch (Exception e) {
        FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage("Error starting transaction: " + e.getMessage()));
        return null;
    }
    EntityManager em = emf.createEntityManager();

    :

    Query q = em.createQuery("SELECT rr FROM RequeueRule rr");

    // Do useful things ...

    em.close();
    try {
        txn.commit();
    } catch (Exception e) {
        FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage("Error committing transaction: " + e.getMessage()));
    }
    :
}
公共类重新查询列表\u返回{
/*
*注入的资源。。。
*/
@资源用户事务txn;
@持久性单位实体管理工厂emf;
:
公共列表GetRequeQueules(){
/* 
*我们需要一个围绕这段代码的硬事务,即使它只是一个查询
*否则,我们无法使用DB2 XA数据源执行此操作:
* 
*com.ibm.db2.jcc.am.SqlException:[jcc][t4][10120][10898][3.63.75]无效操作:结果集已关闭。错误代码=-4470,SQLSTATE=null
*/
试一试{
txn.begin();
}捕获(例外e){
FacesContext.getCurrentInstance().addMessage(空,
新的FacesMessage(“启动事务时出错:+e.getMessage());
返回null;
}
EntityManager em=emf.createEntityManager();
:
Query q=em.createQuery(“从重新查询rr中选择rr”);
//做有用的事情。。。
em.close();
试一试{
提交();
}捕获(例外e){
FacesContext.getCurrentInstance().addMessage(空,
新的FacesMessage(“提交事务时出错:+e.getMessage());
}
:
}

}

如果您只是使用jdbc连接DB2,而没有使用Hibernate等,那么也会出现此错误。因为在DB29.7的新JDBC版本中,
  try{      
    conn = ConnectionFactory.getConnection(ApplicationConstants.LOCAL_DATASOURCE_JNDI_NAME);
    sql="select role_id,role_sname,role_sdesc from db2admin.mng_roles "+sql_condition+" order by role_id asc";
    pt = conn.prepareStatement(sql.toString());
    System.out.println("sql ="+sql);
    rs = pt.executeQuery();
    while(rs.next()){
                i++;
                role_id=rs.getInt(1);
                role_sname=PubFunction.DoNull(rs.getString(2)).trim();
                role_sdesc=PubFunction.DoNull(rs.getString(3)).trim();
                role_right=PubFunction.DoNull(newright.getRightsbyRole(null,role_id)).trim();}