HibernateException:在级联期间刷新是危险的 [英] HibernateException: Flush during cascade is dangerous

查看:508
本文介绍了HibernateException:在级联期间刷新是危险的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时我的应用程序中会出现格式错误的异常。异常接踵而来,如下所示:

 引起:java.lang.reflect.InvocationTargetException $ b $ sun。 reflection.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个常见框架省略

由org.springframework.orm.jpa引起。 JpaSystemException:提交事务时出错;嵌套异常是javax.persistence.RollbackException:在提交org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:294)
时,在org.springframework.orm.jpa处提交事务
时出错。 ExtendedEntityManagerCreator $ ExtendedEntityManagerSynchronization.convertCompletionException(ExtendedEntityManagerCreator.java:483)
在org.springframework.orm.jpa.ExtendedEntityManagerCreator $ ExtendedEntityManagerSynchronization.afterCommit(ExtendedEntityManagerCreator.java:464)
在org.springframework.transaction.support。 TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:90)

导致:javax.persistence.RollbackException:在org.hibernate.ejb.TransactionImpl.commit提交事务
时出错(TransactionImpl.java :71)
在org.springframework.orm.jpa.ExtendedEntityManagerCreator $ ExtendedEntityManagerSynchronization.afterCommit(ExtendedEntityManagerCreat or.java:461)
...省略52个常见框架

引起:org.hibernate.HibernateException:级联冲洗在org.hibernate.impl中是危险的
。 SessionImpl.flush(SessionImpl.java:996)
在org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
在org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)

在数据库上执行select查询时会发生如下情况:

  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_1 6_,
archive0_.MESSAGE_VERSION作为MESSAGE10_16_,
archive0_.PAYLOAD作为PAYLOAD16_,
archive0_.SERVICE_NAME作为SERVICE12_16_,
archive0_.TYPE_OF_SERVICE作为TYPE13_16_,
archive0_.TIME_TO_LIVE as TIME14_16_,
archive0_.TRANSACTION_ID作为TRANSAC15_16_
来自LOGGING.ARCHIVED_MESSAGES archive0_
其中archive0_.MESSAGE_ID =?和archive0_.SERVICE_NAME =?

或:

 选择audit0_.AUDIT_ID作为AUDIT1_17_,
audit0_.CODE作为CODE17_,
audit0_.FLOW_NAME作为FLOW3_17_,
audit0_.KEY_FIELD_NAME作为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作为TRANSPORT16_17_
从LOGGING.AUDIT audit0_
where audit0_.TRANSACTION_ID =?
和(audit0_.LOG_TIME在?和?之间)
order by audit0_.LOG_TIME

第一个查询是Archive类的命名查询,如下所示:

  @Entity 
@Table(schema = LOGGING,name =ARCHIVED_MESSAGES)
@NamedQuery(name =findArchiveByMessageIdAndServiceName,query =选择ar从存档ar WHERE ar.messageId =:messageId和ar.serviceName =:serviceName)
public class Archive实现Serializable {
private static final long serialVersionUID = 1L;

这是由此方法调用的:

  public Archive findArchive(String database,Audit audit){
LOGGER.debug(findArchive {},audit);
setEntityManager(database);
javax.persistence.Query查询;
Archive archive = null;

//获取查询
query = em.createNamedQuery(findArchiveByMessageIdAndServiceName);

//设置参数
query.setParameter(messageId,audit.getMessageId());
query.setParameter(serviceName,audit.getServiceName());

尝试{
List archives = query.getResultList();
if(archives!= null&& archives.size()!= 0)
archive =(Archive)archives.get(0);
} catch(NoResultException e){
//确定并非所有审计记录都有匹配的存档,但是...
} catch(异常e){
//任何其他错误是一个问题
LOGGER.error(找不到档案,e);
}

return archive;
}

第二个被这个方法调用:

  @SuppressWarnings(unchecked)
public Iterator findByCriteria(Criteria criteria,int first,int count){
LOGGER.debug( findByCriteria {},criteria);
setEntityManager(criteria.getDatabase());
StringBuffer queryString = new StringBuffer();
查询查询;

queryString.append(SELECT MAX(a.code),MIN(a.logTime),MAX(a.logTime),
+a.transactionId作为transactionId,a。发件人为发件人,a.receiver为收件人);

//添加common where子句
queryString.append(FROM Audit a where a.logTime BETWEEN:from AND:to);
//根据
//值设置
附加适当的附加条件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);
}


//我们需要一个总结,所以让我们按照常见的ID来分组
queryString.append(GROUP BY a.transactionId,a.sender,a .receiver);

//通过子句添加订单
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);

//总是有和来自
query.setParameter(from,criteria.getFromDate());
query.setParameter(to,criteria.getToDate());

//根据设置的内容设置其余参数
if(criteria.getSender()!= null){
query.setParameter(sender,criteria.getSenderValue( ));
}

//如果设置了
if(criteria.getFilter()。getSender()!= null){
query,用筛选器覆盖搜索条件。 setParameter(sender,criteria.getFilter()。getSender());如果(criteria.getReceiver()!= null){
query.setParameter(receiver,criteria.getReceiverValue());
}

if ()。
}

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()
+%);
}
//设置限制
query.setFirstResult(first);
query.setMaxResults(PAGE_SIZE);

Iterator iterator = query.list()。iterator();
session.close();
返回迭代器;



$ b $ p
$ b

这两种方法都应该设置用户通过setEntityManager(database)选择的数据库; > / p>

我不知道是什么原因导致此异常!有没有人知道这件事?

解决方案

最有可能的问题是线程安全:
我得到这个错误时我试图从同一用户会话中并行访问两个独立线程中的表(相同的浏览器页面有两个并行运行的Ajax请求)。



当我将访问权限更改为序列号时,删除了它。不知道这是否与你同样的问题,值得一试。

Sometimes I get a malformed exception in my application. Exceptions come one after another as the following:

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)

It occurs when a select query is executed on database such as the followings:

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 Archive class like this:

@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 one 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 should set the database that user chooses by setEntityManager(database);

I do not know what causes to occuring this exception! Does anyone know anything about it?

解决方案

Most likely the issue is with Thread Safety : I got this error when I was trying to access the tables from two separate threads in parallel from the same user session (same browser page had two ajax requests running in parallel).

Got rid of it when I changed the access to serial. Not sure if this is the same issue with you, worth a try.

这篇关于HibernateException:在级联期间刷新是危险的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆