JPA/Hibernate verwijderen entiteit soms niet werkt

Ik heb de volgende code dat werkt meestal goed:

public void delete(T object)
{
  EntityManager em = getPersistence().createEntityManager();
  EntityTransaction et = em.getTransaction();
  try
  {
    et.begin();
    object = em.find(object.getClass(), object.getId());
    em.remove(object);
    em.flush();
    et.commit();
  }
  catch(Exception e)
  {
    error("Unable to delete " + object.toString() + ": there are references to it.");
  }
  finally
  {
    if (et.isActive()) et.rollback();
    em.close();
  }
}

Voor veel van mijn entity klassen dit werkt gewoon. Maar voor twee van hen is het niets doet, is het niet gooien eventuele uitzonderingen en niet het object verwijderen. Het log uit de slaapstand laat zien dat de slaapstand voert een aantal query ‘ s selecteren, maar het is niet eens probeert uit te voeren van een verwijderen.

Ik heb al geprobeerd suggesties gevonden in andere soortgelijke vragen hier en hier, maar het mocht niet baten (nou ja, de laatste suggereert @Transactional die ik niet kan gebruiken, maar ik hierbij de instructies tussen begin() en commit() in de plaats).

Ik kan niet lijken te vinden van wat die twee klassen hebben meer (of minder) dan de anderen. Ze gebruiken @PrimaryKeyJoinColumn net als bijna alle andere entiteiten die ik heb, hebben ze @OneToMany en @ManyToOne net als ohters. Om eerlijk te zijn, ze hebben een @OneToOne(optional = false) veld dat verwijst naar een andere klasse en dat andere entiteiten niet hebben, maar ik zou niet gaan door de ruzie van het veranderen van die (en dus het veranderen van de database-schema), tenzij u mij zou er een reden voor is.

Is @OneToOne verantwoordelijk? Of is mijn delete-code afgeluisterd?

  • Heb je geprobeerd om toe te voegen sommige cascade.ALLE en een orphanRemoval= true ?
  • het was juist het tegenovergestelde probleem, ik had te veel css in plaats, zie Steve Ebersole het antwoord hieronder.

 

5 Replies
  1. 85

    Heb je verenigingen in deze grafiek dat een cascade aanhouden terug naar het ding wordt verwijderd? Als dat zo is, de PPV-spec staten duidelijk dat de aanbieder te annuleren verwijder in een dergelijk geval. Als dit het geval is, Hibernate schrijft een logboek met de stelling: “de vn-plannen entiteit verwijdering […]”. Je kon zien dat door het inschakelen van trace in te loggen op de org.hibernate.event.internal.DefaultPersistEventListener logger.

    Als dit de situatie is, je nodig hebt om schoon te maken de verenigingen, zoals vereist door de PPV-specificatie.

    • dat betekent bijvoorbeeld dat als ik het nodig CascadeType voor het Aanhouden van de Eigenaar moet worden geannoteerd?
    • Als u de cascade te blijven, kunt u laten zitten. Zorg ervoor dat voor het verwijderen van de entiteit, uw code verwijdert van de bovenliggende lijst en stelt de ouder als null.
    • Ik heb geen idee hoe het inschakelen van logboekregistratie voor org.slaapstand.evenement.interne.DefaultPersistEventListener :/
    • Een beetje triest dat zo ‘ n gedrag gebeurt in stilte.
    • Waarschijnlijk is het al te laat. Ik gebruik logback. Ik toegevoegd aan logback.xml lijn <logger name="org.hibernate.event.internal.DefaultPersistEventListener" level="TRACE" />. Het werkt.
    • denk dat het hangt er vanaf of je call logging een bericht “stil”. Er is niet echt iets meer kunnen we hier de spec zegt dat dit heeft op het gedrag.
    • “..JPA spec staten duidelijk dat de aanbieder te annuleren verwijder in een dergelijk geval is..”. Kunt u verwijzen naar de pagina waarop deze is beschreven? Ik ben het zoeken in de spec-met het woord “annuleren” en niet iets vinden.

  2. 26

    Het vervangen van de cascade = CascadeType.ALL door orphanRemoval = true in de @OneToMany vereniging geeft het verwachte resultaat: De onderliggende records correct zijn verwijderd zonder de noodzaak van het verwijderen van de bovenliggende record.

    Jammer dat de fout niet ingelogd meer duidelijk.

    • Dit is goed als de ouder is verantwoordelijk voor het verwijderen; echter, als het kind is verantwoordelijk voor het verwijderen, dit kan worden bereikt door het verwijderen van het element van de ouder (het vernietigen van de referentie), dan is het verwijderen van het kind.
  3. 5

    Ik heb hetzelfde probleem als volgende dingen verzameld.

    1. Slaapstand 3.6.10.Laatste
    2. Bovenliggende entiteit met geen referentie naar het Kind.
    3. Sommige Onderliggende entiteit met verwijzing naar de Ouder. Het is legacy code.

      class ChildEntity {
        @ManyToOne(cascade = CascadeType.ALL)
        private ParentEntity parent;
      }
    4. Kind entiteit is geladen in sessie context en vervolgens wordt verwijderd uit de tabel zonder JPA kennisgeving binnen een transactie (opgeslagen procedure sql)

    5. Dan ouder kan niet worden verwijderd. Geen verwijdering, geen uitzondering, alleen ‘vn-schema verwijderen’ bericht in de TRACE-log.

    Oplossing: ik verwijderd cascade kenmerk. Het was een beetje moeilijk voor mij om die Kind entiteit blokken Ouder verwijdering. Ook begrijp ik niet waarom een Kind cascade van invloed als ik Moedermaatschappij.

  4. 0

    Naast dit alles, als je eenmaal hebt al Cascade en Wees correct, in mijn geval vond ik een andere reden waarom het WISSEN kan niet worden gemaakt, ook als alles ziet er prima en zelfs bij het VERWIJDEREN zijn in de log, maar de database niet te zien veranderen.

    Het kan ook een transactionele probleem, maar in mijn geval was dat de Sleutel (in de Oracle-Database) binnen de delete query is een CHAR(8) soort gegevens in de Database, in dat geval kunt u vinden in de documentatie van Oracle CHAR versus VARCHAR2 als uw gegevens niet 8 lengte, de rest is bedek met lege en een PPV VERWIJDEREN maken onderscheid tussen “0001” en “0001 “.

    Ik schrijf deze reactie door ik zie niet in iets als dit in al mijn onderzoek en iemand anders kon krijgen door dit bericht en heb het zelfde probleem.

    Proost.

    • Terwijl dit antwoord brengt een aantal nuttige dingen naar de tafel, het doet niet echt antwoord op mijn vraag. Als je kijkt naar de code die u ziet het is gewoon onmogelijk om een verkeerde waarde van de sleutel, omdat de functie laadt de entiteit (object variabele) vooraf: als er geen entiteit voor de toets, object is van nul en remove() genereert een Uitzondering volgens de specificatie die is niet wat ik meemaakte.
  5. 0

    Ik had het zelfde probleem met een entiteit die vele relaties. Wat ik deed was ingesteld op null-de ouder entiteiten, om een samenvoegen, maak dan een flush en duidelijk en tot slot krijgen de entiteit opnieuw met het vinden en verwijderen. Bijvoorbeeld:

    objAgreement.setParent(null);
    em.merge(objAgreement);
    em.flush();
    em.clear();
    
    objAgreement= em.find(Agreement.class, objAgreement.getId())
    em.remove(objAgreement);

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *