web-gelistirme-sc.com

silinen nesne basamakla yeniden kaydedilir (silinen nesneyi ilişkilerden kaldır)

aşağıdaki iki varlığa sahibim:

1- OynatmaListesi:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade =   CascadeType.ALL)
@OrderBy("adOrder")
private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
  • CascadeType.ALL : çalma listesi öğesini kaydederken veya güncellerken PlaylistadMap koleksiyonunda kaydetmek ve güncellemek için gereklidir.
  • orphanRemoval = true : çalma listesi öğesini silerken gereklidir, PlaylistadMap referansları da silinmelidir.

2- PlaylistadMap:

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "fk_playlist", referencedColumnName = "pkid", nullable = false)
private Playlist playlist;

getCurrentSession().delete(); işlevini kullanarak bir çalma listesini silerken aşağıdaki istisnayı alıyorum:

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)

lütfen bu istisnayı nasıl çözeceğinizi bildiriniz.

43
Mahmoud Saleh

FetchType to Lazy değiştirdikten sonra sorun çözüldü

21
Mahmoud Saleh

Çözüm, istisna iletisinin size söylediklerini tam olarak yapmaktır:

Nedeni: org.hibernate.ObjectDeletedException: silinen nesne cascade tarafından yeniden kaydedilir ( silinen nesneyi ilişkilerden kaldır )

Silinen nesneyi içinde bulunduğu ilişkilendirmelerden (kümeler, listeler veya haritalar) kaldırın. Özellikle, PlayList.PlaylistadMaps öğesinden şüpheleniyorum. Sadece nesneyi silmek yeterli değildir, ona atıfta bulunan herhangi bir basamaklı koleksiyondan kaldırmanız gerekir.

Aslında, koleksiyonunuzda orphanRemoval = true olduğundan, açıkça silmeniz gerekmez. Sadece setten çıkarman gerekiyor.

40
Tom Anderson

Bilmiyorsanız, hangi koleksiyon nesnenizi tutuyor

Benim durumumda, TomAnderson'ın çözümünü uygulamak gerçekten zordu, çünkü bir nesnenin bağlantısını tutan koleksiyonun ne olduğunu bilmiyordum, işte bu, hangi nesnelerin silinmiş olanın bağlantısını tutan olduğunu bilmenin yolu: hata ayıklayıcı, istisna atılmadan önce en düşük yürütme yığını seviyesine girmelisiniz, entityEntry adlı bir değişken olmalıdır, bu nedenle bu değişkenden PersistenceContext nesnesini alırsınız: entityEntry.persistenceContext.

Benim için persistenceContext bir StatefulPersistenceContext örneğiydi ve bu uygulamada, öğeyi içeren koleksiyon hakkında bilgi alabileceğiniz private field parentsByChild var.

Eclipse hata ayıklayıcısını kullanıyordum, bu yüzden bu özel alanı düz bir şekilde elde etmek biraz zordu, bu yüzden Detail Formatter ( - Hata ayıklama yaparken diğer nesnelerin özel alanlarını doğrudan IDE içinde nasıl izleyebilirim? )

Bu bilgiyi aldıktan sonra TomAnderson'ın çözümü uygulanabilir.

5
Dmitry Ginzburg

Bunu aşağıdaki kodu yazarak çözebildim. .Delete () yerine executeUpdate kullandım

def publicSupport = caseObj?.client?.publicSupport
        if(publicSupport)
            PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id])
            //publicSupport.delete()
2
user742102

Bu istisna mesajıyla da karşılaştım ..__Benim için sorun farklıydı . Bir ebeveyni silmek istedim.

Bir işlemde:

  • İlk önce ebeveyni veritabanından aradım.
  • Sonra ebeveyndeki koleksiyondan bir alt öğe çağırdım. 
  • Sonra altta bir alana referans verdim (id)
  • Sonra ebeveyni sildim.
  • Sonra taahhüt çağırdım.
  • "Silinen nesne yeniden kaydedilecek" hatası aldım.

İki ayrı işlem yapmam gerektiği ortaya çıktı. Ardından silme işlemi için yeni bir işlem başlatıldı. 

Alt öğelerin silinmesine veya üst öğedeki koleksiyonların boşaltılmasına gerek yoktu (orphanRemoval = true. Varsayımıyla). Aslında, bu işe yaramadı.

Özetle, bu hata silinirken, bir alt nesne içindeki bir alana referansınız varsa bu hata görünür.

2
Jake

Burada bir çeşit başlangıç ​​oluyor.

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);
            }
        }
    }
1
Ben Tennyson

Yukarıdaki tüm çözümlerin uykuda nasıl çalışmadığı bazıları 5.2.10.Final.

Ancak haritayı aşağıdaki gibi null değerine getirmek benim için çalıştı:

playlist.setPlaylistadMaps(null);
1
KayV

Başka bir geçici çözüm

redochka ve Nikos Paraskevopoulos ile tamamen katılıyorum. Mahmoud Saleh 'in cevabı bazı durumlarda her seferinde değil, sorunun üstesinden gelir. Benim durumumda gerçekten Eager fetchtype ihtiyacım var. Mesela Stony yukarıda belirtildiği gibi. İşte kodum:

Rju varlığı

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 varlığı

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..........
}

ve benim 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);

    }
     .........................
}
1
Frank

İhtiyaç duyduğum için FetchType olmakEAGER, tüm ilişkilendirmeleri kaldırıp (null) ayarlayarak nesneyi (veritabanındaki tüm ilişkilendirmeyi kaldıran) kaydeder, sonra silin!

Bu birkaç milisaniye ekler ancak benim için sorun olmaz, çünkü bu MS'i yorumunuzu eklemeye devam etmenin daha iyi bir yolu varsa ..

Birisi yardımcı olur umarım :)

0
Smile2Life

Bu sorun, PlayList yerine PlaylistadMap modunu kullanarak silerseniz oluşur .. __ bu durumda FetchType = Lazy doğru seçenek değildir. Bir istisna atmaz, ancak yalnızca PlaylistadMap'ten gelen veriler silinir, PlayList'teki veriler tabloda kalır. ayrıca kontrol et.

0
RAGINROSE

Ben de aynı istisnayı yaşadım, çocuğu kişiden uzaklaştırmaya çalışırken (Person - OneToMany - Kid) . Kişi tarafında açıklama:

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

Çocuk tarafında ek açıklama:

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

Böylece çözüm, cascade = CascadeType.ALL 'u kaldırmak oldu, sadece basit: Kid sınıfındaki @ManyToOne ve beklendiği gibi çalışmaya başladı.

0
Oleh Podolyan

Bu hatayı kötü tasarlanmış bir veritabanında da gördüm, burada Person tablosu ile bir one2many ilişkisi olan bir Code tablosu ve aynı Organization tablosu ile bir one2many ilişkisi olan bir Code tablosu vardı. Kurallar duruma bağlı olarak hem bir Kuruluş hem de bir Kişi için geçerli olabilir. Hem Person nesnesi hem de Organizasyon nesnesi Cascade = Tüm yetimleri silme olarak ayarlandı.  

Ancak, Kod tablosunun bu aşırı kullanımı, ne oldu, ne Kişi ne de Kuruluşun silme basamağını yapamamasıydı; çünkü her zaman referansı olan başka bir koleksiyon vardı. Bu yüzden, Java kodunda, hangi referans koleksiyonlarından veya silme işleminden başarısız olursa olsun silinen ne olursa olsun silinir. Çalışmanın tek yolu, kaydetmeye çalıştığım koleksiyondan silmek, sonra doğrudan Kod tablosundan silmek ve ardından koleksiyonu kaydetmek oldu. Bu şekilde referans yoktu.

0
Uncle Iroh

Aynı hatayı vardı. Nesneyi modelden çıkarmak, numarayı yaptı. 

Hatayı gösteren kod:

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();
}
0
Martin Pfeffer

Ben de aynı sorunu yaşıyordum. Aynı işlemi silmeye ve eklemeye çalışıyordum. theEntityManager.flush();'dan sonra theEntityManager.remove(entity); ekledim.

0
Jai

Bu gönderi, kaskad sorununun nerede olduğunu tespit etmek için harika bir numara içeriyor:
Eğer hatayı bulana kadar ve sonra soruna neden olan basamağı tespit edinceye kadar, Cascade.None() ile o sırada Cascade üzerinde değiştirmeyi deneyin.

Sonra sorunu ya orijinal basamağı başka bir şeye değiştirerek ya da Tom Anderson cevabını kullanarak çözün.

0