2010-07-21 9 views
12
@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@Table(name = "company_policies") 
@DiscriminatorColumn(name = "rule_name") 
public abstract class AbstractPolicyRule implements Serializable { 

    @Transient 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private Long id; 
    private String value; 

    ... 
} 

_Sieroty pozostają w bazie danych nawet z orphanRemoval = true na jeden-do-wielu relacji (JPA/Hibernate)

@Entity 
public class Category implements Serializable { 

    @Transient 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private Long id; 
    @Column(name = "category_name") 
    private String name; 

    @OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval = true) 
    @JoinColumn(name = "category_policy_id", referencedColumnName = "id") 
    private Set<AbstractPolicyRule> activePolicyRules; 

    ... 
} 

Kiedy ten zestaw jest aktualizowana istniejące activePolicyRules mają swoje category_policy_id wartość null w baza danych i nowe są wstawione. Chciałbym, aby oryginalne zostały usunięte.

Myślałem dodanie orphanRemoval = true to zrobić, ale tak nie jest. Inne pytania, które widziałem na ten temat, wydają się mieć dwukierunkowe relacje i ustawienie rodzica na wartość null rozwiązuje to, ale nie jest to dwukierunkowa relacja.

Wszelkie sugestie?

Korzystanie Hibernate 3.5.3

Edit: Dzieje się tak tylko wtedy, gdy istnieje istniejąca AbstractPolicyRule w bazie danych, usunąć go z listy, a następnie ponownie zapisać kategorię. Jego klucz obcy, category_policy_id, ma wartość null, a nie jest usuwany.

[DEBUG] Collection found: [domain.category.Category.activePolicyRules#1], was: 
[<unreferenced>] (initialized) 
[DEBUG] Flushed: 0 insertions, 2 updates, 0 deletions to 2 objects 
[DEBUG] Flushed: 1 (re)creations, 0 updates, 1 removals to 1 collections 
... 
[DEBUG] Deleting collection: [domain.category.Category2.activePolicyRules#1] 
[DEBUG] about to open PreparedStatement (open PreparedStatements: 0, globally: 0) 
[DEBUG] update company_policies set category_policy_id=null where category_policy_id=? 
[DEBUG] done deleting collection 

próbował również stół dołączyć ponieważ dokumentacja Hibernate zniechęca poprzedni sposób:

@Entity 
public class Category implements Serializable { 

    @Transient 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private Long id; 
    @Column(name = "category_name") 
    private String name; 

    @OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval = true) 
    @JoinTable(name = "policy_rule_mapping", 
    joinColumns = @JoinColumn(name = "category_id"), 
    inverseJoinColumns = @JoinColumn(name = "rule_id")) 
    private Set<AbstractPolicyRule> activePolicyRules; 

    ... 
} 

to ma ten sam problem. Wiersz tabeli odwzorowań zostanie usunięty, ale AbstractPolicyRule nadal zawiera usunięty element.

+0

Scenariusz, który testowałem, był bardzo bliski Twojej edycji. Zmieniłem mój test, aby usunąć istniejący element z kolekcji bez dodawania kolejnego i nadal jest usuwany. Zauważ, że nie używam żadnego dziedziczenia (myślę, że możesz być). –

Odpowiedz

9

używam orphanRemoval=true z jednokierunkowym stowarzyszenia jeden-do-wielu bez żadnego problemu.

I rzeczywiście, ja testowałem kodu i następujący scenariusz (AbstractPolicyRule wykonawczych equals/hashCode poprawnie):

Category category = new Category(); 
AbstractPolicyRule policyRule1 = new AbstractPolicyRule("foo"); 

category.addToActivePolicyRules(policyRule1); 
em.persist(category); 
em.flush(); 

assertNotNull(category.getId()); 
assertNotNull(category.getActivePolicyRules()); 
assertEquals(1, category.getActivePolicyRules().size()); 

category.removeFromActivePolicyRules(policyRule1); 
category.addToActivePolicyRules(new AbstractPolicyRule("bar")); 
// category = em.merge(category); // works with or without 
em.flush(); 
assertEquals(1, category.getActivePolicyRules().size()); 

tylko działa zgodnie z oczekiwaniami. Poniżej wygenerowanych śladów:

 
22:54:30.817 [main] DEBUG org.hibernate.SQL - insert into Category (id, category_name) values (null, ?) 
Hibernate: insert into Category (id, category_name) values (null, ?) 
22:54:30.824 [main] TRACE org.hibernate.type.StringType - binding null to parameter: 1 
22:54:30.844 [main] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 1 
... 
22:54:30.872 [main] DEBUG org.hibernate.SQL - insert into AbstractPolicyRule (id, name) values (null, ?) 
Hibernate: insert into AbstractPolicyRule (id, name) values (null, ?) 
22:54:30.873 [main] TRACE org.hibernate.type.StringType - binding 'foo' to parameter: 1 
22:54:30.874 [main] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 1 
... 
22:54:30.924 [main] DEBUG org.hibernate.SQL - update AbstractPolicyRule set category_policy_id=? where id=? 
Hibernate: update AbstractPolicyRule set category_policy_id=? where id=? 
22:54:30.927 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 
22:54:30.928 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 2 
22:54:30.929 [main] DEBUG o.h.p.c.AbstractCollectionPersister - done inserting collection: 1 rows inserted 
22:54:30.929 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1 
... 
22:54:30.945 [main] DEBUG org.hibernate.SQL - insert into AbstractPolicyRule (id, name) values (null, ?) 
Hibernate: insert into AbstractPolicyRule (id, name) values (null, ?) 
22:54:30.948 [main] TRACE org.hibernate.type.StringType - binding 'bar' to parameter: 1 
22:54:30.948 [main] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 2 
... 
22:54:30.990 [main] DEBUG org.hibernate.SQL - update AbstractPolicyRule set category_policy_id=null where category_policy_id=? and id=? 
Hibernate: update AbstractPolicyRule set category_policy_id=null where category_policy_id=? and id=? 
22:54:30.991 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 
22:54:30.992 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 2 
22:54:30.993 [main] DEBUG o.h.p.c.AbstractCollectionPersister - done deleting collection rows: 1 deleted 
22:54:30.993 [main] DEBUG o.h.p.c.AbstractCollectionPersister - Inserting rows of collection: [com.stackoverflow.q3304092.Category.activePolicyRules#1] 
22:54:30.994 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1 
... 
22:54:30.996 [main] DEBUG org.hibernate.SQL - update AbstractPolicyRule set category_policy_id=? where id=? 
Hibernate: update AbstractPolicyRule set category_policy_id=? where id=? 
22:54:30.997 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 
22:54:30.998 [main] TRACE org.hibernate.type.LongType - binding '2' to parameter: 2 
22:54:31.002 [main] DEBUG o.h.p.c.AbstractCollectionPersister - done inserting rows: 1 inserted 
... 
22:54:31.015 [main] DEBUG org.hibernate.SQL - delete from AbstractPolicyRule where id=? 
Hibernate: delete from AbstractPolicyRule where id=? 
22:54:31.017 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 

Pierwsza reguła zasad zostanie usunięta.

Jeśli to nie jest reprezentatywna, co robisz, powinieneś może dostarczyć więcej kodu.

Aktualizacja: Odbieranie komentarz z PO ...

Wow Właśnie zmienił wezwanie saveOrUpdate scalić i teraz to usunięcie odpowiednio. Wiesz, dlaczego tak jest?

tylko domyślać: od orphanRemoval jest rzeczą JPA, zastanawiam saveOrUpdate zajmie odpowiednio z nim (rzeczywiście, myślałem, że używając EntityManager API ponieważ wspomniane JPA).

+0

Dzięki za odpowiedź. Zaktualizowałem swój wpis, podając więcej informacji, które mam nadzieję mają sens. – Josh

+0

Być może nie rozumiem, co oznacza "ustawić równy/kod skrótu". W tej chwili kod equals/hash używa unikalnych identyfikatorów dla tabeli (ale nie id). – Josh

+0

@Josh To dobra implementacja (i użyłem takiej implementacji powyżej, próbując odtworzyć problem). –

3

Najpierw upewnij się, że Twoje klasy implementują metody hashCode() i equals(), tak aby hibernacja wiedziała, że ​​dokładnie te elementy zostały usunięte z zestawu.

Następnie spróbuj zdefiniować adnotację hibernacji @Cascade, określając typ kaskady usuwania i osierocenia tam i obserwatora, czy to samo dzieje się. Jeśli działa tak, jak chcesz - zgłoś błąd w hibernacji i tymczasowo użyj opatentowanej adnotacji. W przeciwnym razie - zaktualizować pytanie ze szczegółami

+0

Dzięki za odpowiedź. Zaktualizowałem swój wpis, dodając więcej informacji. – Josh