Result Set - закрытая ошибка при обращении к таблице через JPA (Websphere и DB2) - PullRequest
2 голосов
/ 28 марта 2012

Я использую IBM Open JPA в WebSphere 7, и у меня возникает проблема, когда я пытаюсь сослаться на объект @ManyToOne и продолжаю получать следующую ошибку от DB2:

com.ibm.db2.jcc.b.SqlException: [jcc] [t4] [10120] [10898] [3.50.152] Недопустимая операция: набор результатов закрыт. ОШИБКА = -4470, SQLSTATE = ноль

Я дергаюсь за то, почему это не работает, и надеюсь, что кто-то может помочь.

Вот упрощенное представление схем базы данных:

Таблица отчета

record_id - integer - (первичный ключ - сгенерирован DB2)

agency - integer not null (внешний ключ к раскрывающейся таблице)

Раскрывающийся список таблиц

record_id - integer - (первичный ключ - сгенерированный DB2)

Вот сущность JPA для Отчета, которая ссылается на агентство

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="AGENCY")
private Dropdown agency;

Вот код, в котором я выполняю именованный запрос, чтобы получить данные, а затем просто перебираю набор результатов для распечатки идентификатора отчета и зависимости. Всякий раз, когда вызывается report.getAgency (), я получаю ошибку «набор результатов закрыт» из 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;
}

если я никогда не обращаюсь к методу getAgency, я могу напечатать что-нибудь еще об отчете без проблем. Это только кажется со ссылкой на 2-й таблицы. Есть идеи?

Ответы [ 3 ]

3 голосов
/ 10 мая 2012

Я ответил на это в ответах на свой первоначальный комментарий, но понял, что никогда не отмечал вопрос как ответивший, поэтому я хотел сделать это официально.

Исправление задокументировано здесь: https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.doc/ae/tejb_jpatroubleshoot.html

Исправление закончилось тем, что параметр resulSetHoldability должен был быть 1 вместо 2

Для источников данных XA вы должны установить downgradeHoldCursorsUnderXa в true, иначе вы можете получить исключение персистентности с этимсообщение:

An SQL OPEN for a held cursor was issued on a XA connection
1 голос
/ 05 июня 2013

Установка DB2 resultSetHoldability = 1 будет работать, только если вы используете источник данных не-XA.Если вам нужно сохранить 2PC, то это не решение.

У меня возникла именно эта проблема, и в конце концов она была решена путем жесткого кодирования транзакции вокруг кода, вызывающего сбой.Вот что у меня есть:

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()));
    }
    :
}

}

0 голосов
/ 16 декабря 2015

Если вы просто используете jdbc для подключения к DB2 и не используете Hibernate и т. Д., Вы также получите эту ошибку. Потому что в новой версии JDBC с DB2 9.7 многие функции, которые вы не должны поддерживать в новой версии, несмотря на то, что в старой версии jdbc нет ошибок.

Эти функции включают в себя. 1: PreparedStatement старая версия

pt.executeUpdate(sql);

новая версия

pt.executeUpdate();

2: итерация соединения

старая версия:

  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(conn,role_id)).trim();}

новая версия

  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();}
...