2013-06-03 21 views
21

Mam następujący kod, który zazwyczaj działa dobrze:JPA/Hibernate usunąć podmiot czasami nie działa

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

dla wielu z moich klas encji to po prostu działa. Jednak dla dwóch z nich nic nie robi, nie rzuca żadnych wyjątków i nie usuwa obiektu. Dziennik ze stanu hibernacji pokazuje, że hibernacja wykonuje kilka wybranych zapytań, ale nawet nie próbuje wykonać usunięcia.

Ja już próbowałem propozycje znajdujące się w innych podobnych pytań here i here, ale bezskutecznie (dobrze, to ostatnie sugeruje @Transactional których nie mogę używać, ale ja po prostu zamknięty sprawozdań między begin() i commit() zamiast).

Nie mogę znaleźć tego, co te dwie klasy mają więcej (lub mniej) niż inne. Używają one @PrimaryKeyJoinColumn, tak jak prawie wszystkie inne podmioty, które posiadam, mają one @OneToMany i @ManyToOne po prostu jak. Szczerze mówiąc, mają one pole @OneToOne(optional = false), które odwołuje się do innej klasy i że inne jednostki nie mają, ale nie będę przechodził przez kłopotów z ich zmienianiem (i w konsekwencji zmieniania schematu bazy danych), chyba że powiesz mi, że może być powodem tego.

Czy jest odpowiedzialny za @OneToOne? Czy mój błąd kasowany jest błędnie?

+0

Czy próbowałeś dodać kaskadę .ALL i orphanRemoval = true? – willome

+0

@willome: to był tylko problem odwrotny, miałem "zbyt dużo" kaskadowania w miejscu, zobacz poniżej odpowiedź Steve'a Ebersole'a. –

Odpowiedz

58

Czy na tym wykresie znajdują się skojarzenia, które powodują, że trwa powrót do usuwanej rzeczy? Jeśli tak, specyfikacja JPA stwierdza wyraźnie, że dostawca ma w takim przypadku anulować usunięcie. W takim przypadku Hibernate wypisze instrukcję dziennika, która mówi "usunięcie obiektu poza harmonogramem [...]". Można to zobaczyć, włączając rejestrowanie śledzenia w rejestratorze org.hibernate.event.internal.DefaultPersistEventListener.

Jeśli tak jest, należy wyczyścić te powiązania zgodnie z wymaganiami specyfikacji JPA.

+0

To był problem, wielkie dzięki! –

+0

oznacza to na przykład, że jeśli potrzebuję CascadeType dla Persist, strona Właściciel powinna być adnotowana? – Sergio

+4

Jeśli potrzebujesz kaskady, możesz ją zostawić. Upewnij się tylko, że przed usunięciem encji twój kod usuwa go z listy nadrzędnej i ustawia rodzica jako wartość null. – Rian

18

Zastąpienie cascade = CascadeType.ALL przez orphanRemoval = true w skojarzeniu @OneToMany daje oczekiwany wynik: Rekordy podrzędne są poprawnie usuwane bez konieczności usuwania rekordu nadrzędnego.

Szkoda, że ​​błąd nie jest rejestrowany jaśniej.

+1

Jest to dobre, jeśli rodzic jest odpowiedzialny za usunięcie; jednak jeśli dziecko jest odpowiedzialne za usunięcie, można to osiągnąć przez usunięcie elementu z elementu nadrzędnego (zniszczenie odnośnika), a następnie usunięcie elementu potomnego. – Thomas

4

Mam ten sam problem, gdy śledzę rzeczy zebrane razem.

  1. Hibernate 3.6.10.Final
  2. jednostka nadrzędna z nr odniesienia do dziecka.
  3. Niektóre jednostki podrzędne w odniesieniu do jednostki nadrzędnej. Jest to starszy kod.

    class ChildEntity { 
        @ManyToOne(cascade = CascadeType.ALL) 
        private ParentEntity parent; 
    } 
    
  4. jednostka Dziecko jest ładowany do ramach sesji, a następnie jest usuwany z tabeli, bez powiadamiania JPA w transakcji (procedury przechowywanej, języka SQL)

  5. Następnie macierzysty nie mogą być usunięte. Bez usuwania, bez wyjątków, w dzienniku TRACE po prostu "nieumyślne usunięcie".

Rozwiązanie: Usunąłem atrybut kaskady. Trochę trudno było mi ustalić, która encja Dziecko blokuje usuwanie rodzica.Ponadto nie rozumiem, dlaczego kaskada Dziecko ma wpływ na usunięcie elementu nadrzędnego.