2009-01-20 4 views
10

Mam dwie powiązane klajty z przypisami JPA. Alarm i status. Jeden alarm może mieć jeden status.JPA nie generuje "przy usuniętym zbiorze zerowym" Ograniczenia FK

To, czego potrzebuję, to móc usunąć jeden status i "propagować" wartość pustą do alarmów znajdujących się w tym statusie, który został usunięty.

To znaczy, że klucz obcy należy zdefiniować jako "w zestawie usunięć zerowych".

@Entity 
public class Alarm { 
    @Id 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence") 
    @SequenceGenerator(name="sequence", sequenceName="alarm_pk_seq") 
    private Integer id; 

    @OneToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="idStatus") 
    private Status status; 

    // get/set 
} 

@Entity 
public class Status { 
    @Id 
    @Column(name="idStatus") 
    private Integer id; 

    private String description; 

    // get/set 
} 

przykład:

Przed:

STATUS 
id description 
1 new 
2 assigned 
3 closed 

ALARMS 
id status 
1 1 
2 2 
3 2 

Po (usunięcie stanu id = 2)

STATUS 
id description 
1 new 
3 closed 

ALARMS 
id status 
1 1 
2 NULL 
3 NULL 

mi stosując hibernacji i PostgreSQL automatyczne generowanie bazy z kodu źródłowego. Próbowałem z każdym możliwym CascadeType bez powodzenia.

Czy coś jest nie tak z kodem? Czy można to zrobić za pomocą JPA?

Odpowiedz

0

Czy jesteś pewien swojego @OneToOne? Wydaje mi się, że wolisz używać @ManyToOne (jako stan może mieć wpływ kilka alarmów):

@Entity 
public class Alarm { 
    ... 

    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="idStatus", nullable=true) 
    private Status status; 

    ... 
} 
+0

Dziękuję. Masz rację, właśnie zmieniłem to na relację ManyToOne i dodałem parametr zerowy = true, ale wynik jest wciąż taki sam :( –

3

Wystarczy dodać, że za pomocą adnotacji Hibernacja:

@OnDelete(action=OnDeleteAction.CASCADE) 

generuje zagraniczny key as: "W AKTUALIZACJI NIE AKCJI NA USUŃ KASKADĘ;"

Ale nie ma action = OnDeleteAction.SET_NULL

Ponadto, nie podoba mi się związać mój kod do hibernacji, jeśli to możliwe (ale mogę z tym żyć, czy to działa).

Omówi to thread. Nie mogę uwierzyć, że nie istnieje łatwa metoda w JPA (lub rozszerzeniach Hibernate) do generowania klucza obcego.

2

W twoim przypadku generujesz bazę danych z klas. Sugerowałoby to, że nie użyjesz bazy danych do innych celów (ponieważ spowodowałoby to konieczność posiadania skryptów DDL). Oznacza to, że ta reguła zaimplementowana w bazie danych lub w kodzie java jest nieistotna.

Wiemy również, że Hibernacja spowodowałaby wyjątek przejściowy w przypadku, gdy jeden z nich usunąłby jeden lub więcej statusów i spróbowałby odwoływać się do niego podczas zatwierdzania bez kaskady.

Ponadto baza danych zostanie wygenerowana przy użyciu ograniczenia klucza obcego.

Wszystko to oznacza, że ​​ograniczenie musi być przestrzegane, aby aplikacja działała.

Jeśli twoje jednostki znajdują się w słoiku samodzielnie, możesz dodać metodę przejściową do alarmu lub interfejsu statusu, aby usunąć status z zachowaniem reguły.

Ponadto, programiści korzystający z tych elementów będą zmuszeni przestrzegać reguły, bo inaczej kod nie zadziała. Aby ułatwić zadanie, można utworzyć relację dwukierunkową, dzięki czemu łatwiejsze będzie śledzenie alarmów ze stanów.

Jeśli możesz, użyj wbudowanego przechwytywacza/odbiornika, aby ustawić właściwość alarm.status na wartość null.

-1

OpenJPA ma

@ForeignKey(deleteAction=ForeignKeyAction.NULL) 

, ale nie ma standardowego sposobu JPA, aby to zrobić (i najwyraźniej jest to niemożliwe przy Hibernacji).

Sprawia, że ​​chcę wrócić do JDO.

Powiązane problemy