org.hibernate.AssertionFailure

时间:2011-06-25 09:50:59

标签: hibernate transactions

我的线程执行时有时会遇到这个奇怪的错误。这可能与什么有关?

2011-Jun-25 09:05:22,339 ERROR AssertionFailure:45 - an assertion failure occured (this             may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: null id in com.inrev.bm.bean.IRKeyWordTweet entry (don't flush the Session after an exception occurs)
    at         org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:78)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:187)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.inrev.bm.streaming.IRKeyWordStreaminThread.run(IRKeyWordStreaminThread.java:119)

我的插入代码,

    Transaction tx = null;
    Session session = sessionFactory.openSession();
    tx = session.beginTransaction();

    int count = 0;
    try
    {
        for (Iterator itrList = statusToInsert.iterator(); itrList.hasNext();) 
        {
            try 
            {
                IRecord record = (IRecord) itrList.next();
                session.save(record);
                count++;
                if ( count % 10 == 0 ) 
                { 
                    session.flush();
                    session.clear();
                    tx.commit();
                    tx = session.beginTransaction();
                }

            }
            catch (Exception e) 
            {
                tx.commit();
                session.close();
                session = sessionFactory.openSession();
                tx = session.beginTransaction();
                StringWriter sw = new StringWriter(); 
                PrintWriter pw = new PrintWriter(sw); 
                e.printStackTrace(pw); 
                log.error(sw.toString());
            }
        }
    }
    catch (Exception e) {
        StringWriter sw = new StringWriter(); 
        PrintWriter pw = new PrintWriter(sw); 
        e.printStackTrace(pw); 
        log.error(sw.toString());
    }
    finally {
        tx.commit();
        session.close();
    }

此致

罗希特夏尔

3 个答案:

答案 0 :(得分:32)

问题是你的代码正在处理一个异常,这在99.9%的情况下是坏事,坏事,并且发生以下情况:

与会话的其中一个交互在try块中失败,并引发异常。发生这种情况时,会话无效,并且不能使用用于绝对任何,因为它处于不一致状态。但是你的代码与catch块中的会话交互,触发了断言。

会话异常后唯一安全的做法是回滚事务并关闭它。任何其他类型的交互都可能会生成另一个异常(在这种情况下是一个断言异常)。

答案 1 :(得分:3)

一个没有干净处理的用例是某种轮询器。如果应用程序正在为大型后台作业设置一些“进行中状态”,则提交,然后分离线程/ http请求/会话轮询,而异步后台线程抛出异常,异步线程需要负责捕获该异常并且在轮询器轮询的事物上将状态标记为“失败”。在这种情况下,它的笨拙的b / c会话被低级别的hibernate异常的b / c无效。这似乎是捕获和处理异常的有效案例。

唯一可以解决新会议的问题吗?在像Seam这样的托管交易环境中干净/标准的方式吗?

答案 2 :(得分:0)

除了@Augustoanswer:

在档案UserDAOImpl.java

@Override
public int addUser(User user) {

    // Maintain Hibernate session manually 
    Session openSession = sessionFactory.openSession();

    int retVal = 0;

    try {
        openSession.getTransaction().begin();
        openSession.persist(user);
        openSession.getTransaction().commit();
        retVal = 1;
    } catch (HibernateException e) {
        openSession.getTransaction().rollback();
        retVal = -1;
    } finally {
        openSession.close();
    }
    return retVal;
}