开发者

org.hibernate.AssertionFailure

I am getting this strange error sometimes while my thread executes. What could this be related to?

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.hibern开发者_JS百科ate.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)

My code for inserting,

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

Regards,

Rohit


The problem is that your code is handling an Exception, which is a bad, bad thing to do in 99.9% of the cases, and the following is happening:

One of the interactions with the session fails in the try block, and throws an exception. When this happens, the session is invalidated and cannot be used for absolutely anything as it's in an inconsistent state. But your code interacts with the session in the catch block, which triggers the assertion.

The only safe thing to do after an exception with the session, is to rollback the transaction and close it. Any other type of interaction will probably generate another exception (in this case an assertion exception).


one use case that is not cleanly handled is a poller of some kind. If an application is setting some "in progress status" for a large background job, commits, then separate thread/http request/session polling, while an async background thread throws an exception, that async thread needs to be responsible to catch that exception and mark the status as "failed" on the thing the poller is polling. In this case its awkward b/c the session gets invalidated b/c of a low level hibernate exception. This seems to be a valid case to catch and handle exceptions.

Is the only work around to get a new session? Clean/standard way of doing that within a managed transaction env like Seam?


In addition to @Augustoanswer:

In the file 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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜