HibernateException: Flush dangerous during cascade

Sometimes I get the wrong exception in my application. Exceptions occur one after another as follows:

Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedMethodAccessor77.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:183) ... 22 common frames omitted Caused by: org.springframework.orm.jpa.JpaSystemException: Error while commiting the transaction; nested exception is javax.persistence.RollbackException: Error while commiting the transaction at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:294) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerSynchronization.convertCompletionException(ExtendedEntityManagerCreator.java:483) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerSynchronization.afterCommit(ExtendedEntityManagerCreator.java:464) at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:90) Caused by: javax.persistence.RollbackException: Error while commiting the transaction at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerSynchronization.afterCommit(ExtendedEntityManagerCreator.java:461) ... 52 common frames omitted Caused by: org.hibernate.HibernateException: Flush during cascade is dangerous at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:996) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54) 

This happens when a select query is executed in the database, for example:

 select archive0_.ARCHIVE_KEY as ARCHIVE1_16_, archive0_.ARCHIVE_DATE as ARCHIVE2_16_, archive0_.ARCHIVE_TYPE as ARCHIVE3_16_, archive0_.DELETION_DATE as DELETION4_16_, archive0_.ENCODING as ENCODING16_, archive0_.FILENAME as FILENAME16_, archive0_.JMSPROPERTIES as JMSPROPE7_16_, archive0_.MESSAGE_ID as MESSAGE8_16_, archive0_.MESSAGE_TYPE as MESSAGE9_16_, archive0_.MESSAGE_VERSION as MESSAGE10_16_, archive0_.PAYLOAD as PAYLOAD16_, archive0_.SERVICE_NAME as SERVICE12_16_, archive0_.TYPE_OF_SERVICE as TYPE13_16_, archive0_.TIME_TO_LIVE as TIME14_16_, archive0_.TRANSACTION_ID as TRANSAC15_16_ from LOGGING.ARCHIVED_MESSAGES archive0_ where archive0_.MESSAGE_ID=? and archive0_.SERVICE_NAME=? 

or

 select audit0_.AUDIT_ID as AUDIT1_17_, audit0_.CODE as CODE17_, audit0_.FLOW_NAME as FLOW3_17_, audit0_.KEY_FIELD_NAME as KEY4_17_, audit0_.KEY_FIELD_VALUE as KEY5_17_, audit0_.LOG_TIME as LOG6_17_, audit0_.MESSAGE_ID as MESSAGE7_17_, audit0_.MESSAGE_SIZE as MESSAGE8_17_, audit0_.MESSAGE_TYPE as MESSAGE9_17_, audit0_.MESSAGE_TYPE_VERSION as MESSAGE10_17_, audit0_.PRIORITY as PRIORITY17_, audit0_.RECEIVER as RECEIVER17_, audit0_.SENDER as SENDER17_, audit0_.SERVICE_NAME as SERVICE14_17_, audit0_.TRANSACTION_ID as TRANSAC15_17_, audit0_.TRANSPORT_ID as TRANSPORT16_17_ from LOGGING.AUDIT audit0_ where audit0_.TRANSACTION_ID=? and (audit0_.LOG_TIME between ? and ?) order by audit0_.LOG_TIME 

The first query is a named query for the Archive type as follows:

 @Entity @Table(schema = "LOGGING", name = "ARCHIVED_MESSAGES") @NamedQuery(name = "findArchiveByMessageIdAndServiceName", query = "SELECT ar FROM Archive ar WHERE ar.messageId = :messageId and ar.serviceName = :serviceName") public class Archive implements Serializable { private static final long serialVersionUID = 1L; 

which is called by this method:

 public Archive findArchive(String database, Audit audit) { LOGGER.debug("findArchive {}", audit); setEntityManager(database); javax.persistence.Query query; Archive archive = null; // Get the query query = em.createNamedQuery("findArchiveByMessageIdAndServiceName"); // Set the parameters query.setParameter("messageId", audit.getMessageId()); query.setParameter("serviceName", audit.getServiceName()); try { List archives = query.getResultList(); if(archives != null && archives.size() != 0) archive = (Archive) archives.get(0); } catch (NoResultException e) { // Ok so not all audit records have a matching archive but... } catch (Exception e) { // Any other error is a problem LOGGER.error("Failed to find archive", e); } return archive; } 

The second is called by this method:

 @SuppressWarnings("unchecked") public Iterator findByCriteria(Criteria criteria, int first, int count) { LOGGER.debug("findByCriteria {}", criteria); setEntityManager(criteria.getDatabase()); StringBuffer queryString = new StringBuffer(); Query query; queryString.append("SELECT MAX(a.code), MIN(a.logTime), MAX(a.logTime), " + "a.transactionId as transactionId, a.sender as sender, a.receiver as receiver "); //Add the common where clause queryString.append(" FROM Audit a where a.logTime BETWEEN :from AND :to"); // Append the appropriate addition where clauses depending on what // values are set if (criteria.getSender() != null || criteria.getFilter().getSender() != null) { queryString.append(" AND a.sender = :sender"); } if (criteria.getReceiver() != null || criteria.getFilter().getReceiver() != null) { queryString.append(" AND a.receiver = :receiver"); } if (criteria.getMessageType() != null || criteria.getFilter().getMessageType() != null) { queryString.append(" AND a.messageType = :messageType"); } if (criteria.getTransactionId() != null || criteria.getFilter().getTransactionId() != null) { queryString .append(" AND a.transactionId = :transactionId"); } if (criteria.getKeyFieldValue() != null || criteria.getFilter().getKeyFieldValue() != null) { queryString .append(" AND UPPER(a.keyFieldValue) LIKE :keyFieldValue"); } // We want a summary so lets group by the common ids queryString.append(" GROUP BY a.transactionId, a.sender, a.receiver "); // Add order by clause if (criteria.getOrderBy() != null) { queryString.append(" ORDER BY "); queryString.append(criteria.getOrderBy()); queryString.append(criteria.isAscending() ? " ASC" : " DESC"); } Session session = ((Session) em.getDelegate()).getSessionFactory().openSession(); query = session.createQuery(queryString.toString()); query.setReadOnly(true); query.setFetchSize(Integer.valueOf(1000)); query.setCacheable(true); query.setCacheMode(CacheMode.NORMAL); // Will always have from and to dates query.setParameter("from", criteria.getFromDate()); query.setParameter("to", criteria.getToDate()); // Set remaining parameters depending on what is set if (criteria.getSender() != null) { query.setParameter("sender", criteria.getSenderValue()); } // Override the search criteria with the filter if set if (criteria.getFilter().getSender() != null) { query.setParameter("sender", criteria.getFilter().getSender()); } if (criteria.getReceiver() != null) { query.setParameter("receiver", criteria.getReceiverValue()); } if (criteria.getFilter().getReceiver() != null) { query.setParameter("receiver", criteria.getFilter().getReceiver()); } if (criteria.getMessageType() != null) { query.setParameter("messageType", criteria.getMessageTypeValue()); } if (criteria.getFilter().getMessageType() != null) { query.setParameter("messageType", criteria.getFilter() .getMessageType()); } if (criteria.getTransactionId() != null) { query.setParameter("transactionId", criteria.getTransactionId()); } if (criteria.getFilter().getTransactionId() != null) { query.setParameter("transactionId", criteria.getFilter() .getTransactionId()); } if (criteria.getKeyFieldValue() != null) { query.setParameter("keyFieldValue", "%" + criteria.getKeyFieldValue().toUpperCase() + "%"); } if (criteria.getFilter().getKeyFieldValue() != null) { query.setParameter("keyFieldValue", "%" + criteria.getFilter().getKeyFieldValue().toUpperCase() + "%"); } // Set the limits query.setFirstResult(first); query.setMaxResults(PAGE_SIZE); Iterator iterator = query.list().iterator(); session.close(); return iterator; } 

Both methods must install the database that the user selects setEntityManager (database);

I do not know what are the reasons for this exception! Does anyone know about this?

+7
source share
2 answers

Most likely, the problem is related to thread safety: I got this error when I tried to access tables from two separate threads in parallel with the same user session (there were two parallel ajax requests on the same browser page).

It got rid of when I changed access to serial. Not sure if this is the same problem with you, it's worth a try.

+6
source

I investigated a similar problem for several days. Supra's answer points me in the right direction: thread safety.

The fact is that Session in Hibernate is not thread safe, and we should not allow 2 threads to access a single session. This is one of the possible causes of the "Reset when cascading is dangerous" error. Two access streams for the same session can cause a lot of unexpected behavior, because Hibernate is not designed for this.

I usually use a framework for this kind of thing, but if you need to do it yourself, you can do a static ThreadLocal .

TL; DR : SessionFactory is thread safe, Session is not. Provide one new session for each thread (either do it yourself or using the DI framework)

+3
source

All Articles