【问题标题】:Getting SQLException: Operation not allowed after ResultSet closed获取 SQLException:ResultSet 关闭后不允许操作
【发布时间】:2020-06-17 15:36:00
【问题描述】:

我正在使用 Hibernate 会话,我基本上是在尝试更新表,但同时在更新之前我需要确保表中不存在该插入条目。 注意:这基本上是一个每天都会运行的 cron 作业,我只需要根据一些逻辑插入新记录。

这是我的代码的 sn-p:

    ... 
    ....

    ScrollableResults scroll = 
                crit.addOrder(Order.asc("expireDate"))
                .scroll();   // this will give list on daily basis which I need to filter out
            session.beginTransaction();
            Query query = session.createQuery("from SD"); 

            List<SD> sdObjectList= query.list(); // This is to do select statement so I can compare the list with new entry in while loop below
            List<String> sdList= new ArrayList<String>();  // to hold only strings extracted frm sdObjectList

            for(SD sd: sdObjectList) {
                sdList.add(sd.getName());
            }
            session.beginTransaction();
            while(scroll.next()) {        // --> This line throws error 
                Foo foo_obj = (Foo) scroll.get(0);
                // foo_obj will have unique id as well as name
                if (sdList.contains(foo_obj.getName())) {
                    out.println("**SKIPPING foo_obj, since already in DB " + foo_obj.getName());
                    continue;
                }
                SD sd= new SD(); 
                SD.setdID(foo_obj.getId());
                SD.setName(foo_obj.getName());
                SD.setStatus("xyz");
                session.save(SD);

                FooObjList.add(foo_obj);
            }   
            //Commit the transaction
            session.getTransaction().commit();
            scroll.close();

这是错误:

   [java] Jun 16, 2020 10:52:32 PM org.hibernate.util.JDBCExceptionReporter logExceptions
     [java] WARNING: SQL Error: 0, SQLState: S1000
     [java] Jun 16, 2020 10:52:32 PM org.hibernate.util.JDBCExceptionReporter logExceptions
     [java] SEVERE: Operation not allowed after ResultSet closed
     [java] org.hibernate.exception.GenericJDBCException: could not advance using next()
     [java]     at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
     [java]     at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
     [java]     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
     [java]     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
     [java]     at org.hibernate.impl.ScrollableResultsImpl.next(ScrollableResultsImpl.java:127)
     [java]     at com.netnation.jobs.snapnames.list.GenerateList.main(GenerateList.java:199)
     [java] Caused by: java.sql.SQLException: Operation not allowed after ResultSet closed
     [java]     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
     [java]     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
     [java]     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
     [java]     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
     [java]     at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:794)
     [java]     at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7139)
     [java]     at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:2859)
     [java]     at org.hibernate.impl.ScrollableResultsImpl.next(ScrollableResultsImpl.java:122)
     [java]     ... 1 more

有人可以建议如何解决吗?或者任何其他更好的方法来处理整个逻辑?

注意: 我刚刚意识到这两个 session.beginTransaction() 没有抛出任何错误,但我不确定它是否是好的做法,我是否正确关闭它? hibernate session 是否还提供任何其他更好的方法来实现上述场景?

但是当我删除第一个 session.beginTransaction() 时,它确实抛出了上面的错误。

【问题讨论】:

  • 不要调用beginTransaction()两次,调用它之前调用scroll(),调用scroll.close()之前调用commit() .
  • 可悲的是,它仍然抛出同样的错误。我认为添加两个单独的 beginTransaction() 应该可以解决它

标签: java mysql hibernate session


【解决方案1】:

您无需检查实体是否存在。这不是必需的:

if (sdList.contains(foo_obj.getName())) {
    out.println("**SKIPPING foo_obj, since already in DB " + foo_obj.getName());
    continue;
}

因为,您是通过以下方式自己设置主键:

SD.setdID(foo_obj.getId());

并且您没有使用任何自动生成的 id 工具,当您执行 save 时,Hibernate 将首先通过 SELECT 检查实体是否存在。如果是,则执行UPDATE,否则执行INSERT

现在,直到第一个循环在 WHILE 循环中的哪个位置执行?请注意,如果抛出异常,您将无法再重用该会话,这可能解释了 ResultSet 被关闭的原因。

【讨论】:

    猜你喜欢
    • 2011-08-16
    • 2015-02-04
    • 2012-06-11
    • 2011-12-01
    • 2017-04-17
    • 2018-03-20
    相关资源
    最近更新 更多