2009-01-20 1 views
10

Ich habe zwei verwandte Klassen JPA-annotiert. Alarm und Status. Ein Alarm kann einen Status haben.JPA generiert nicht "on delete set null" FK Einschränkungen

Was ich brauche, ist in der Lage, einen Status zu löschen und einen Nullwert an die Alarme, die in diesem Status sind, die gelöscht wurde, zu "propagieren".

Das heißt, ich brauche den Fremdschlüssel definiert als "auf löschen Null Null gesetzt".

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

Beispiel:

Vorher:

STATUS 
id description 
1 new 
2 assigned 
3 closed 

ALARMS 
id status 
1 1 
2 2 
3 2 

Nach (Löschen den Status mit id = 2)

STATUS 
id description 
1 new 
3 closed 

ALARMS 
id status 
1 1 
2 NULL 
3 NULL 

ich Hibernate und PostgreSQL verwenden, die Datenbank automatisch zu erzeugen aus dem Quellcode. Ich habe mit jedem möglichen CascadeType ohne Erfolg versucht.

Ist im Code etwas falsch? Ist es möglich, dies mit JPA zu tun?

Antwort

0

Sind Sie sicher mit Ihrem @OneToOne? Es scheint mir, dass Sie eher @ManyToOne verwenden würde (als Status mehrere Alarme können betroffen sein):

@Entity 
public class Alarm { 
    ... 

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

    ... 
} 
+0

Vielen Dank. Du hast Recht, ich habe es gerade in eine ManyToOne-Beziehung geändert, und ich habe den Nullable = true-Parameter hinzugefügt, aber das Ergebnis ist immer noch dasselbe :( –

3

nur hinzufügen, dass die Hibernate Annotations mit:

@OnDelete(action=OnDeleteAction.CASCADE) 

den Außen erzeugt Taste wie: "ON UPDATE KEINE AKTION AUF DELETE CASCADE;"

Aber es gibt keine action = OnDeleteAction.SET_NULL

Darüber hinaus Ich mag es nicht meinen Code zu binden Hibernate, wenn möglich (aber ich kann damit leben, wenn es funktioniert).

Diese thread diskutiert es. Ich kann nicht glauben, dass es in JPA (oder Hibernate-Erweiterungen) keine einfache Methode gibt, den Fremdschlüssel zu generieren.

2

In Ihrem Fall generieren Sie die Datenbank aus den Klassen. Dies würde bedeuten, dass Sie die Datenbank nicht für andere Zwecke verwenden (da Sie dadurch DDL-Skripte erzwingen würden). Das bedeutet, dass diese Regel in der Datenbank oder im Java-Code implementiert ist, ist unwichtig.

Wir wissen auch, dass Hibernate eine vorübergehende Ausnahme auslösen würde, wenn man einen oder mehrere Status löschen und versuchen würde, sie zu referenzieren, wenn man ohne eine Kaskade festlegt.

Die Datenbank wird auch mithilfe einer Fremdschlüsseleinschränkung generiert.

All dies bedeutet, dass die Einschränkung eingehalten werden muss, damit die Anwendung funktioniert.

Wenn sich Ihre Entitäten in einem Jar selbst befinden, können Sie dem Alarm oder der Statusschnittstelle eine Übergangsmethode hinzufügen, um einen Status unter Einhaltung der Regel zu entfernen.

Auch die Programmierer, wenn die Entitäten verwendet werden, werden gezwungen, die Regel zu respektieren, sonst funktioniert der Code nicht. Aber um die Aufgabe zu erleichtern, könnten Sie die Beziehung bidirektional machen, um die Alarmverfolgung aus den Status zu erleichtern.

Wenn Sie können, verwenden Sie einen OnDelete-Interceptor/Listener, um die Eigenschaft alarm.status auf null zu setzen.

-1

OpenJPA hat

@ForeignKey(deleteAction=ForeignKeyAction.NULL) 

aber es gibt keine Standard-JPA-Möglichkeit, dies zu tun (und anscheinend ist es unmöglich mit Hibernate).

Macht mich wollen zurück zu JDO.

Verwandte Themen