HibernateException:在级联期间刷新是危险的 [英] HibernateException: Flush during cascade is dangerous
问题描述
引起: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屋!