55

我有以下两个实体:

1- 播放列表:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade =   CascadeType.ALL)
@OrderBy("adOrder")
private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
  • CascadeType.ALL:在保存或更新播放列表实体时需要在 PlaylistadMap 集合上保存和更新。
  • orphanRemoval = true:删除播放列表实体时需要,PlaylistadMap 引用也应删除。

2- 播放列表地图:

@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)

请告知如何解决此异常。

4

19 回答 19

58

解决方案是完全按照异常消息告诉您的操作:

引起:org.hibernate.ObjectDeletedException:已删除的对象将被级联重新保存(从关联中删除已删除的对象

从它所在的关联(集合、列表或映射)中删除已删除的对象。特别是,我怀疑,来自PlayList.PlaylistadMaps. 仅删除对象是不够的,您必须将其从任何引用它的级联集合中删除。

事实上,既然你的收藏有orphanRemoval = true,你不需要明确地删除它。您只需要将其从集合中移除。

于 2012-07-25T12:40:45.767 回答
25

将FetchType更改为Lazy后问题解决

于 2012-07-26T10:57:45.487 回答
7

如果您不知道,哪个集合包含您的对象

就我而言,应用 TomAnderson 的解决方案真的很困难,因为我不知道集合是什么,它包含指向对象的链接,所以这是知道哪些对象包含指向已删除对象的链接的方法:在调试器你应该在抛出异常之前进入最低执行堆栈级别,应该有一个名为 的变量entityEntry,所以你PersistenceContext从这个变量中得到一个对象:entityEntry.persistenceContext

对我来说persistenceContext是一个实例,StatefulPersistenceContext这个实现有privatefield parentsByChild,您可以从中检索有关包含该元素的集合的信息。

我使用的是Eclipse调试器,所以很难直接检索这个私有字段,所以我使用了Detail Formatter调试时如何直接在IDE中查看其他对象的私有字段?

得到这些信息后,就可以应用 TomAnderson 的解决方案了。

于 2016-09-04T08:42:24.157 回答
3

上述所有解决方案在hibernate 5.2.10.Final中都不起作用。

但是将地图设置为 null 如下对我有用:

playlist.setPlaylistadMaps(null);
于 2017-11-29T10:19:42.160 回答
3

我也遇到了这个异常消息。对我来说,问题是不同的。我想删除父母。

在一笔交易中:

  • 首先,我从数据库中调用了父级。
  • 然后我从父集合中调用了一个子元素。
  • 然后我引用了孩子(id)中的一个字段
  • 然后我删除了父级。
  • 然后我打电话给提交。
  • 我收到“已删除的对象将被重新保存”错误。

事实证明,我必须进行两次单独的交易。我在引用子字段后承诺。然后为删除开始一个新的提交。

无需删除子元素或清空父元素中的集合(假设orphanRemoval = true.)。事实上,这并没有奏效。

总之,如果在删除子对象时引用了子对象中的字段,则会出现此错误。

于 2015-07-22T00:08:14.150 回答
2

我可以通过编写下面的代码来解决这个问题。我使用了 executeUpdate 而不是 .delete()

def publicSupport = caseObj?.client?.publicSupport
        if(publicSupport)
            PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id])
            //publicSupport.delete()
于 2013-04-10T07:07:00.627 回答
1

一种开始在这里进行。

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);
            }
        }
    }
于 2015-06-22T18:00:48.260 回答
1

另一种解决方法

我完全同意redochkaNikos Paraskevopoulos的观点。Mahmoud Saleh的回答在某些情况下并非每次都能解决这个问题。在我的情况下,我真的需要 Eager fetchtype。因此,正如上面提到的Stony一样,我刚刚从一个包含该对象的列表中删除了该对象。这是我的代码:

Rju实体

public class Rju extends AbstractCompany implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 4294142403795421252L;


    //this field just duplicates @Column(name="callname") and serves for mapping to Rju fullname field
    @Column(name = "fullname")
    private String namerju;
    @NotEmpty
    @Column(name = "briefname")
    private String briefname;

    @LazyCollection(LazyCollectionOption.FALSE)
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "otd")
    private Collection<Vstan> vStanCollection;

//  @LazyCollection(LazyCollectionOption.FALSE)
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "rju", orphanRemoval = true)
    private Collection<Underrju> underRjuCollection;
.........
}

Underrju实体

public class Underrju extends AbstractCompany implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 2026147847398903848L;


    @Column(name = "name")
    private String name;

    @NotNull
    @Valid
    @JoinColumn(name = "id_rju", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Rju rju;
......getters and setters..........
}

和我的UnderrjuService

@Service("underrjuService")
@Transactional
public class UnderRjuServiceImpl implements UnderRjuService {

    @Autowired
    private UnderRjuDao underrjuDao;

    .............another methods........................
    @Override
    public void deleteUnderrjuById(int id) {
        Underrju underrju=underrjuDao.findById(id);
        Collection<Underrju> underrjulist=underrju.getRju().getUnderRjuCollection();
        if(underrjulist.contains(underrju)) {
            underrjulist.remove(underrju);
        }
        underrjuDao.delete(id);

    }
     .........................
}
于 2018-06-06T06:15:57.653 回答
1

我遇到了同样的问题。我试图在同一个事务中删除和插入。我 theEntityManager.flush();在之后添加theEntityManager.remove(entity);

于 2017-06-19T21:02:27.073 回答
0

我在一个设计糟糕的数据库上也遇到了这个错误,其中有一个Person表与一个表具有 one2many 关系,Code而一个表与同一个Organization表具有 one2many 关系Code。视情况而定,本准则可同时适用于组织或个人。 Person 对象和 Organization 对象都设置为 Cascade=All delete orphans。

然而,这种过度使用 Code 表的结果是 Person 和 Organization 都不能级联删除,因为总是有另一个集合引用它。因此,无论它是如何在 Java 代码中从任何引用集合或对象中删除的,删除都会失败。让它工作的唯一方法是将它从我试图保存的集合中删除,然后直接将它从代码表中删除,然后保存集合。这样就没有引用它了。

于 2015-01-02T22:10:57.980 回答
0

因为我需要FetchTypeEAGER,所以我通过将它们设置为(null)来删除所有关联并保存对象(删除数据库中的所有关联)然后删除它!

这会增加一些毫秒,但对我来说很好,如果有更好的方法来保留这些 MS,请在下面添加您的评论..

希望对某人有所帮助:)

于 2014-02-06T12:42:40.663 回答
0

这篇文章包含一个检测级联问题所在位置的绝妙技巧:
尝试在Cascade上替换,Cascade.None()直到您没有收到错误,然后您检测到导致问题的级联。

然后通过将原始级联更改为其他内容或使用汤姆安德森答案来解决问题。

于 2015-10-07T17:11:10.260 回答
0

如果您使用PlaylistadMapmodal 而不是PlayList. 在这种情况下FetchType = Lazy不是正确的选择。它不会抛出任何异常,但只会PlaylistadMap删除来自的数据,其中的数据 PlayList将保留在表中。也检查一下。

于 2018-11-15T11:09:47.563 回答
0

您需要删除映射对象上的关联:

playList.getPlaylistadMaps().setPlayList(null);
session.delete(playList);
于 2020-05-09T22:07:48.707 回答
0

我只是为了解决这个问题。

  1. 我将列表的值设置为
  2. 我保存了对象(它有效)
  3. 我将新数据设置为对象
  4. 我重新保存了对象
  5. 有用。!
于 2019-10-23T07:35:03.210 回答
0

解决方案是“破坏”对象之间的关系,然后再次尝试删除。答案在您的日志中:

(remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]

解释:什么?(删除关联)在哪里?[ID#6 的 PlaylistadMap 对象]

于 2021-01-19T18:50:10.007 回答
0

我有同样的例外,当试图从人身上移除孩子时(Person - OneToMany - Kid)。在人方面注释:

@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, ... cascade    = CascadeType.ALL)
public Set<Kid> getKids() {    return kids; }

在孩子方面注释:

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
public Person getPerson() {        return person;    }

所以解决方案是删除cascade = CascadeType.ALL,很简单: @ManyToOne在 Kid 类上,它开始按预期工作。

于 2016-10-17T20:41:50.900 回答
0

有同样的错误。从模型中移除对象就可以了。

显示错误的代码:

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();
}
于 2017-10-30T12:17:14.353 回答
-1
cascade = { CascadeType.ALL }, fetch = FetchType.LAZY
于 2015-08-21T21:52:37.590 回答