org.hibernate.AssertionFailure: невозможно выполнить удаление, например,
Я получаю эту ошибку утверждения гибернации, когда пытаюсь выполнить чтение после некоторых операций удаления.
Я не смог найти ничего относительно этой ошибки "Невозможно выполнить удаление", кроме кода soure, поэтому я думаю, что, возможно, я делаю что-то явно неправильное...
Трассировка стека ниже,
AssertionFailure:43 - - HHH000099: 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: Unable to perform un-delete for instance X
org.hibernate.AssertionFailure: Unable to perform un-delete for instance X
at org.hibernate.engine.spi.ActionQueue.unScheduleDeletion(ActionQueue.java:508)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:157)
at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870)
at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863)
at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:190)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsDeleted(DefaultPersistEventListener.java:229)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:158)
at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870)
at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863)
at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:190)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsPersistent(DefaultPersistEventListener.java:183)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:147)
at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870)
at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863)
at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:160)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:151)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1186)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1241)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:257)
at org.hibernate.ejb.criteria.CriteriaQueryCompiler$3.getResultList(CriteriaQueryCompiler.java:254)
С Уважением,
10 ответов
У меня была такая же проблема. Случилось так, что я удалял связанные bean-компоненты, назовем их A и B. Я удалил B, а затем приступил к поиску сущностей C, ссылающихся на As, и дал компонент типа A в качестве параметра для запроса, и выполнение запроса вызвало это исключение., Мое лучшее предположение состоит в том, что аннотация Cascade на объекте D, ссылающаяся как на A, так и на B, удалила As, когда я удалил B, а затем предоставил объект, который уже был удален на уровне БД, в качестве параметра для запроса, что вызвало проблему.
Перестановка кода так, чтобы я сначала удалил ссылки из C в A, а затем приступил к удалению как B, так и A, кажется, обходит это.
Я тоже столкнулся с этой же трассировкой стека сегодня, используя Hibernate 4.x в качестве провайдера JPA 2.x. Вот что я узнал о том, что мне нужно было изменить, чтобы исправить это возникшее исключение.
В моей модели сопоставленного домена JPA у меня есть глубокий граф на основе OneToMany, у A много B, у B много C, у C много D, у D много Es. Каскадный тип на всех, кому нужно, - ВСЕ. Обратное указание ManyToOne существует на каждом уровне, и код, который мы написали, работал нормально, когда все отношения ManyToOne были по умолчанию (т.е. загружены с нетерпением)
В случае неправильного использования, который я диагностировал сегодня, мы читаем дискретный набор D с помощью запроса JPQL и, перебирая этот набор, вызываем EntityManager.remove(c), где мы получаем экземпляр c, запрашивая экземпляр D для его родитель / владелец C экземпляр.
Если этот экземпляр c получен из-за отложенной загрузки отношения D к C, вызов EntityManager.remove (c) не вызывает жалоб, но последующий вызов EntityManager.flush() приводит к исключению субъекта.
Предметное исключение НЕ возникает, если в этом JPQL-запросе связь с D до C загружается с помощью добавления "join fetch dc c".
Итак, я подумал, что поделюсь этими результатами на случай, если кто-то еще столкнется с этой проблемой, и вышеизложенное дает им представление о том, что они могут изменить, чтобы заставить проблему замолчать.
Это для всех, кто пришел сюда через поиск не может удалить утверждение (как я).
У меня была та же проблема с Утверждением в каком-то коде, с которым ушел Подрядчик, но для меня проблема была не в каскаде, который работал нормально.
По какой-то причине Hibernate загружал одну и ту же сущность дважды в одном сеансе. Я узнал об этом только когда копался в глубине Hibernate.
Я использовал org.hibernate.stat.SessionStatistics, который вы можете получить из Session и PersistenceContext, который вы получаете из SessionImpl
Session session = (Session)this.entityManager.unwrap(Session.class);
persistenceContext = ((SessionImpl)session).getPersistenceContext();
узнать, что загрузил Hibernate.
Когда я распечатал полный список лиц с
public void printSessionInfo(String where,HashSet<String> printClasses){
Log log = Logging.getLog(PersistentSesionInfo.class);
Session session = (Session)this.entityManager.unwrap(Session.class);
SessionStatistics stats = session.getStatistics();
HashMap<String,Counter> entityMap = new HashMap<String,Counter>();
if(stats!=null){
log.info("EntityManager #0 has #1 managed entities and #2 collections at #3", getHash(entityManager),stats.getEntityCount(),stats.getCollectionCount(),where);
List<EntityKey> entities = com.google.common.collect.Lists.newArrayList(stats.getEntityKeys());
Iterator<EntityKey> iter = entities.iterator();
while(iter.hasNext()){
EntityKey ek = iter.next();
if(entityMap.containsKey(ek.getEntityName())){
entityMap.get(ek.getEntityName()).increase();
}else{
entityMap.put(ek.getEntityName(), new Counter());
}
if(printClasses!=null && printClasses.contains(ek.getEntityName())){
try{
Object o = ((HibernateSessionProxy)session).get(ek.getEntityName(), ek.getIdentifier());
if(o!=null){
log.info("Entity #0 of type #1 id=#2 System hash=#3 object hash #4", o,Hibernate.getClass(o).getSimpleName(),ek.getIdentifier(),Integer.toHexString(System.identityHashCode(o)),Integer.toHexString(o.hashCode()));
}
}catch(javax.persistence.EntityNotFoundException e ){
log.error("Entity #0 with id #1 cannot be found anymore", ek.getEntityName(),ek.getIdentifier());
}
}
}
for(Entry<String,Counter> entry : entityMap.entrySet()){
log.info("Entity #0 count #1", entry.getKey(),entry.getValue());
}
}
}
public class Counter {
int count = 1;
public void increase(){
count++;
}
public int getCount(){
return count;
}
public String toString(){
return String.valueOf(count);
}
}
Мои сущности были перечислены там, но когда я использовал
persistenceContext.getEntry(myEntity)
он возвратил нуль (entityManager.contains (myEntity) вернул true)!
Я перебрал все EntityKeys из persistenceContext.getEntitiesByKey() (вам может понадобиться скопировать список, прежде чем перебирать его)
List<EntityKey> list = new ArrayList<EntityKey>();
list.addAll(persistenceContext.getEntitiesByKey().keySet());
Там был EntityKey для myEntity, но он указывал на другой экземпляр (другой System.identiyHashCode).
Я должен предположить, что в конечном итоге проблема была с методами equals и hashCode объекта (как это часто бывает с проблемами объекта). Я заметил, что похожие экземпляры сущностей будут иметь один и тот же хэш-код, даже если их родительский элемент будет другим.
Я использовал "должен предполагать", поскольку проблема не исчезла сразу (не перезагружал сервер, так как я использую liverebel). Проблема исчезла только после перезапуска сервера с включенной функцией TRACE в Hibernate. После отката всех других отладочных изменений и только оставив методы equals/hashCode, он все еще работал.
Поэтому, когда у вас возникают странные необъяснимые проблемы с вашими сущностями - проверяйте методы equals и hashCode! И используйте Hibernate классы PersistenceContext и SessionStatistics для его отладки.
Я знаю, что это действительно поздний ответ, но это может кому-то помочь, когда-нибудь в будущем!! Этот ответ примерно такой же ошибки (если кто-то ответит на этот вопрос, к счастью): AssertionFailure - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
Я получаю эту ошибку, потому что я пытался save
session
с субъектом которого not-null
атрибут-первичный ключ был установлен в null
,
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "calc_id", unique = true, nullable = false)
private Long calcId;
здесь GenerationType.IDENTITY не работал и не устанавливал значение первичного ключа раньше save
, И Тадаа.... Я получил ту же ошибку, что и упоминал. Поэтому я просто заменил код следующим.
@SequenceGenerator(name="identifier", sequenceName="mytable_id_seq", allocationSize=1)
@GeneratedValua(strategy=GenerationType.SEQUENCE, generator="identifier")
Это может быть ошибка hibernate, если вы читаете (load() экземпляр прокси), а затем вызываете delete и сохраняете его. https://hibernate.atlassian.net/browse/HHH-8374
Мои два цента, для тех, кто прибывает в эту ветку и использует Grails.
В моем случае проблема возникла из-за изменения постоянного свойства домена во временное (с указанием конкретного установщика и получателя) и наличия конструктора, использующего версию карты и передавшего туда переменную.
Исходный класс домена был таким:
class MyDomain {
String content
}
И я создавал экземпляр вроде:
def domain = new MyDomain( content: "sample content" )
Обновленный домен:
class MyDomain {
static transients = [ 'content' ]
byte[] compressed
String getContent() {
compressed ? uncompress( compressed ) : null
}
void setContent( String content ) {
compressed = content ? compress( content ) : null
}
}
Конструктор не будет жаловаться, но setContent не вызывается, и, как ни странно, вместо того, чтобы выдавать ошибку проверки или ошибку SQL, возникает ошибка, упомянутая в этом потоке.
Решение простое:
def domain = new MyDomain()
domain.content = "sample content"
Таким образом, сеттер вызывается.
Я использовал cascade = CascadeType.ALL, и это сработало, предположим, вы получаете его на объекте B, который ссылается на объект A. Пожалуйста, поместите все каскад на объект A,
Также зависит от того, кто поддерживает отношение, в моем случае отношение было отображено A.
Я тоже однажды страдал от этой проблемы. В случае использования двунаправленного отображения, когда мы используем несколько @OneToMany и используем mappedby annotatin, а затем сервер показывает такую ошибку. Таким образом, вы можете легко решить проблему, используя
@JoinTable(name="c",joinColumns=@JoinColumn(name="c_id"),inverseJoinColumns=@JoinColumn(name="l_id"))
вместо использования mappedby..
У меня была такая же ошибка. У меня были классы A и B. B имеет список As, а A имеет ссылку на B. A также имеет ссылку на объект C (Cascade.All), который вызывает исключение при восстановлении.
Я пытался переместить объект A в другой объект B.
Это вызывает исключение:
objectOfA.getObjectOfB().getListOfAs().remove(objectOfA);
objectOfB1.getListOfAs().add(objectOfA);
objectOfA.seObjectOfB(objectOfB1);
dao.flush()
Это было рабочее решение.
objectOfA.seObjectOfB(objectOfB1);
dao.flush()
bjectOfA.getObjectOfB().getListOfAs().remove(objectOfA);
objectOfB1.getListOfAs().add(objectOfA);
Последние две строки не всегда являются обязательными, потому что hibernate исправляет это после перезагрузки.
Я не уверен, если это ошибка в спящем режиме. Возникло исключение, потому что hibernate сравнивает объект C с прокси-сервером того же C с "==" в ActionQueue.unScheduleDeletion()
Удалите методы hashCode и equals из вашей сущности. это работает для меня