我正在WebSphere 7上使用IBM的Open JPA实现,当我尝试引用@ManyToOne的对象并从DB2继续收到以下错误时,我遇到了问题:
com.ibm.db2.jcc.b.SqlException:[jcc] [t4] [10120] [10898] [3.50.152]无效操作:结果集已关闭。 ERRORCODE = -4470,SQLSTATE = null
我正在拔头发,为什么这不起作用,希望有人可以提供帮助。
以下是数据库模式的简化视图:
表格报告
record_id - integer - (主键 - 由DB2生成)
代理 - 整数非空(Dropdown表的外键)
表格下拉
record_id - integer - (主键 - 由DB2生成)
以下是报告的JPA实体,该实体引用了该机构
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="AGENCY")
private Dropdown agency;
以下是我运行命名查询以获取数据然后迭代结果集以打印报告ID和agnency的代码。每当调用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方法,我可以打印出关于报告的任何其他内容而没有任何问题。它似乎只是对第二个表的引用。有什么想法吗?
答案 0 :(得分:3)
我在回答原始评论时回答了这个问题,但意识到我从来没有将问题标记为已回答,所以我想正式做到这一点。
最终修复结果是resulSetHoldability设置需要为1而不是2
对于XA数据源,您必须将downgradeHoldCursorsUnderXa
设置为true
,否则您可能会收到此消息的持久性异常:
An SQL OPEN for a held cursor was issued on a XA connection
答案 1 :(得分:1)
设置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()));
}
:
}
}
答案 2 :(得分:0)
如果您只是使用jdbc连接DB2而没有使用Hibernate等,那么您也会遇到此错误。因为在使用DB2 9.7的新JDBC版本中,许多函数你不应该支持new vesion,尽管在旧版本的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();}