Ответ 1
проблема решена после изменения FetchType на Lazy
i имеет следующие два объекта:
1- PlayList:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade = CascadeType.ALL)
@OrderBy("adOrder")
private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
2- PlaylistadMap:
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "fk_playlist", referencedColumnName = "pkid", nullable = false)
private Playlist playlist;
при удалении списка воспроизведения с помощью getCurrentSession().delete();
я получаю следующее исключение:
org.springframework.dao.InvalidDataAccessApiUsageException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:657)
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy54.deletePlayList(Unknown Source)
at com.xeno.advertisingsuite.web.beans.PlayListBean.deletePlaylist(PlayListBean.java:282)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
... 103 more
Caused by: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]
at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:1220)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:188)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
пожалуйста, сообщите, как исправить это исключение.
проблема решена после изменения FetchType на Lazy
Решение состоит в том, чтобы точно указать сообщение об ошибке:
Вызвано: org.hibernate.ObjectDeletedException: удаленный объект будет повторно сохранен каскадом (удалить удаленный объект из ассоциаций)
Удалите удаленный объект из ассоциаций (наборов, списков или карт), в которых он находится. В частности, я подозреваю, от PlayList.PlaylistadMaps
. Недостаточно просто удалить объект, вам нужно удалить его из любых каскадных коллекций, которые ссылаются на него.
Фактически, поскольку ваша коллекция имеет orphanRemoval = true
, вам не нужно ее явно удалять. Вам просто нужно удалить его из набора.
Я смог решить это, написав код ниже. Я использовал executeUpdate вместо .delete()
def publicSupport = caseObj?.client?.publicSupport
if(publicSupport)
PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id])
//publicSupport.delete()
Я тоже столкнулся с этим сообщением об исключении. Для меня проблема была другая. Я хотел удалить родителя.
В одной транзакции: Сначала я вызвал родителя из базы данных. Затем я вызвал дочерний элемент из коллекции в родительском элементе. Затем я указал одно поле в дочернем элементе (id) Затем я удалил родителя. Затем я вызвал фиксацию. Я получил ошибку "удаленный объект будет сохранен".
Оказывается, мне пришлось сделать две отдельные транзакции. Я сделал это после ссылки на поле у ребенка. Затем была запущена новая фиксация для удаления.
Не нужно было удалять дочерние элементы или пустые коллекции в родительском (предполагая orphanRemoval = true.). На самом деле это не сработало.
В сумме эта ошибка появляется, если у вас есть ссылка на поле в дочернем объекте, когда этот объект удаляется.
В моем случае было очень сложно применить решение TomAnderson, так как я не знал, что такое коллекция, которая содержит ссылку на объект, поэтому здесь можно узнать, какие объекты содержат ссылку на удаленный: в отладчике вы должны ввести самый низкий уровень стека выполнения перед тем, как будет выбрано исключение, должна быть переменная с именем entityEntry
, поэтому вы получаете объект PersistenceContext
из этой переменной: entityEntry.persistenceContext
.
Для меня PersistenceContext
был экземпляром StatefulPersistenceContext
, и эта реализация имеет поле private
parentsByChild
, из которого вы можете получить информацию о коллекции, которая содержит этот элемент.
Я использовал отладчик Eclipse, поэтому было трудно получить это частное поле прямо, поэтому я использовал Detail Formatter
(Как посмотреть частные поля других объектов непосредственно в среде IDE при отладке?)
После получения этой информации можно применить решение TomAnderson.
Вид Начала здесь.
for (PlaylistadMap playlistadMap : playlistadMaps) {
PlayList innerPlayList = playlistadMap.getPlayList();
for (Iterator<PlaylistadMap> iterator = innerPlayList.getPlaylistadMaps().iterator(); iterator.hasNext();) {
PlaylistadMap innerPlaylistadMap = iterator.next();
if (innerPlaylistadMap.equals(PlaylistadMap)) {
iterator.remove();
session.delete(innerPlaylistadMap);
}
}
}
Поскольку мне нужно FetchType быть EAGER, я удаляю все ассоциации, устанавливая их в (null) и сохраняя объект (который удаляет всю ассоциацию в базе данных), тогда удалите его!
Это добавит несколько миллисекунд, но это хорошо для меня, если есть лучший способ сохранить эти MS, добавьте свой комментарий ниже.
Надеюсь, что помогите кому-то:)
Я также столкнулся с этой ошибкой в плохо спроектированной базе данных, где была таблица Person
с отношением one2many с таблицей Code
и таблицей Organization
с отношением one2many с той же таблицей Code
, Кодекс может применяться как к Организации, так и к Личности в зависимости от ситуации. И объект Person, и объект Organization были установлены в Cascade = All delete сирот.
То, что стало с этим перегруженным использованием таблицы кодов, состояло в том, что ни Человек, ни Организация не могли каскадировать удаление, потому что всегда была другая коллекция, в которой была ссылка на нее. Поэтому, независимо от того, как это было удалено в коде Java из любых ссылок на коллекции или объекты, удаление завершилось неудачно. Единственный способ заставить его работать - это удалить его из коллекции, которую я пытался сохранить, а затем удалить ее из таблицы Code непосредственно, а затем сохранить коллекцию. Таким образом, ссылки на него не были.
Этот пост содержит блестящий трюк, чтобы определить, где каскадная проблема:
Попробуйте заменить на Cascade в то время с помощью Cascade.None()
, пока вы не получите ошибку, а затем обнаружите, что каскад вызывает проблему.
Затем разрешите проблему либо путем изменения исходного каскада на что-то еще, либо с помощью ответа Tom Anderson.
У меня было то же исключение, вызванное при попытке удалить ребенка из человека (Person - OneToMany - Kid). В аннотации стороны стороны:
@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, ... cascade = CascadeType.ALL)
public Set<Kid> getKids() { return kids; }
В аннотации стороны Kid:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
public Person getPerson() { return person; }
Таким образом, решение было удалить cascade = CascadeType.ALL
, просто: @ManyToOne
в классе Kid, и он начал работать как ожидалось.
У меня была такая же проблема. Я пытался удалить и вставить в ту же транзакцию. Я добавил theEntityManager.flush();
после theEntityManager.remove(entity);
.
Была та же ошибка. Удаление объекта с модели сделало трюк.
Код, который показывает ошибку:
void update() {
VBox vBox = mHboxEventSelection.getVboxSelectionRows();
Session session = HibernateUtilEventsCreate.getSessionFactory().openSession();
session.beginTransaction();
HashMap<String, EventLink> existingEventLinks = new HashMap<>();
for (EventLink eventLink : mEventProperty.getEventLinks()) {
existingEventLinks.put(eventLink.getEvent().getName(), eventLink);
}
mEventProperty.setName(getName());
for (Node node : vBox.getChildren()) {
if (node instanceof HBox) {
JFXComboBox<EventEntity> comboBoxEvents = (JFXComboBox<EventEntity>) ((HBox) node).getChildren().get(0);
if (comboBoxEvents.getSelectionModel().getSelectedIndex() == -1) {
Log.w(TAG, "update: Invalid eventEntity collection");
}
EventEntity eventEntity = comboBoxEvents.getSelectionModel().getSelectedItem();
Log.v(TAG, "update(" + mCostType + "): event-id=" + eventEntity.getId() + " - " + eventEntity.getName());
String split = ((JFXTextField) (((HBox) node).getChildren().get(1))).getText();
if (split.isEmpty()) {
split = "0";
}
if (existingEventLinks.containsKey(eventEntity.getName())) {
// event-link did exist
EventLink eventLink = existingEventLinks.get(eventEntity.getName());
eventLink.setSplit(Integer.parseInt(split));
session.update(eventLink);
existingEventLinks.remove(eventEntity.getName(), eventLink);
} else {
// event-link is a new one, so create!
EventLink link1 = new EventLink();
link1.setProperty(mEventProperty);
link1.setEvent(eventEntity);
link1.setCreationTime(new Date(System.currentTimeMillis()));
link1.setSplit(Integer.parseInt(split));
eventEntity.getEventLinks().add(link1);
session.saveOrUpdate(eventEntity);
}
}
}
for (Map.Entry<String, EventLink> entry : existingEventLinks.entrySet()) {
Log.i(TAG, "update: will delete link=" + entry.getKey());
EventLink val = entry.getValue();
mEventProperty.getEventLinks().remove(val); // <- remove from model
session.delete(val);
}
session.saveOrUpdate(mEventProperty);
session.getTransaction().commit();
session.close();
}
Некоторые, как все вышеперечисленные решения не работали в спящем режиме 5.2.10.Final.
Но установка карты в значение null, как показано ниже:
playlist.setPlaylistadMaps(null);
cascade = { CascadeType.ALL }, fetch = FetchType.LAZY