2013-03-19 22 views
13

Ich habe eine viele-zu-eins-Beziehung, die ich sein will nullable machen. Kann das jemand erklären? Gibt es eine Möglichkeit, es zum Laufen zu bringen? Beachten Sie, dass ich JBoss 7, JPA 2.0 mit Hibernate als Persistenzanbieter und eine PostgreSQL 9.1-Datenbank verwende.Kann nicht @ManyToOne Beziehung nullable

EDIT:

fand ich die Ursache für mein Problem. Anscheinend ist es aufgrund der Art, wie ich den Primärschlüssel in der referenzierten Einheit definiert Customer:

@Entity 
@Table 
public class Customer { 
    @Id 
    @GeneratedValue 
    @Column(columnDefinition="serial") 
    private int id; 
} 

Es scheint, dass @Column(columnDefinition="serial") für den Primärschlüssel automatisch den Fremdschlüssel setzt es auf NOT NULL in der Datenbank verweist. Ist das wirklich das erwartete Verhalten bei der Angabe des Spaltentyps als serial? Gibt es eine Problemumgehung für das Aktivieren von Nullable-Fremdschlüsseln in diesem Fall?

Vielen Dank im Voraus.

Antwort

9

Ich fand die Lösung für mein Problem. Die Art, wie der Primärschlüssel in der Entität Customer definiert ist, ist in Ordnung, das Problem liegt in der Fremdschlüsseldeklaration.

@ManyToOne 
@JoinColumn(columnDefinition="integer", name="customer_id") 
private Customer customer; 

der Tat, wenn das Attribut columnDefinition="integer" der Fremdschlüssel wird standardmäßig weggelassen wird als die Quellspalte eingestellt werden: Es sollte so erklärt werden, ein nicht-null Serien mit seiner eigenen Sequenz. Das ist natürlich nicht das, was wir wollen, da wir nur wollen, dass die automatisch inkrementierte ID referenziert wird, nicht um eine neue zu erstellen.

Außerdem scheint es, dass das Attribut name=customer_id auch erforderlich ist, wie ich bei einigen Tests beobachtet habe. Andernfalls wird die Fremdschlüsselspalte weiterhin als Quellspalte festgelegt. Das ist meiner Meinung nach ein merkwürdiges Verhalten. Kommentare oder zusätzliche Informationen zur Klärung sind willkommen! Der Vorteil dieser Lösung besteht schließlich darin, dass die ID von der Datenbank generiert wird (nicht von JPA) und wir uns daher keine Gedanken darüber machen müssen, wenn Daten manuell oder über Skripte eingefügt werden, die häufig bei der Datenmigration oder -wartung vorkommen .

0

Das ist sehr seltsam.

In JPA Nullable-Parameter ist standardmäßig true. Ich benutze diese Art von Konfiguration die ganze Zeit und es funktioniert gut. Wenn Sie versuchen, eine Entität zu speichern, sollte sie erfolgreich sein.

Haben Sie versucht, eine Tabelle zu löschen, die für diese Beziehung erstellt wurde? Vielleicht haben Sie Legacy-Tabelle mit dieser Spalte?

Oder vielleicht sollten Sie versuchen, eine Lösung für andere Teile des Codes zu finden, weil dies die richtige Konfiguration ist.

Hinweis: Ich habe diese Konfiguration auf PostgreSQL mit JPA2 und Hibernate versucht.

EDIT

In diesem Fall können Sie vielleicht ein wenig andere Definition von Primärschlüssel versuchen.

Zum Beispiel können Sie Definition wie folgt verwendet werden:

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column() 
private Long id; 

und postgresql wird

id bigint NOT NULL 
-- with constraint 
CONSTRAINT some_table_pkey PRIMARY KEY (id) 

erzeugen Wenn diese gut genug ist, können Sie diese Lösung versuchen.

+0

erklärt sich gezeigt, dass in der Tat ist eine Lösung, die ich in Betracht gezogen haben. Leider ermöglicht dies nicht die ID-Generierung von der Datenbank selbst, und es ist eine Funktionalität, die ich brauche, wenn ich Daten manuell einfüge (zum Beispiel mit import.sql von hibernate). Zum Glück denke ich, ich bin dabei, eine Lösung zu finden. Ich mache nur ein paar Tests und wenn es erfolgreich ist, werde ich die Lösung veröffentlichen. Danke für Ihre Hilfe. – vcattin

7

ich auf dieses Problem kam, aber ich konnte es auf diese Weise lösen:

@ManyToOne 
@JoinColumn(nullable = true) 
private Customer customer; 

Vielleicht ist das Problem von @ManyToOne(optional = true)

+6

'nullable = false' ?? "falsch"? Warum "falsch", nicht "wahr"? – Andremoniy

+0

definitiv sollte es 'nullable = true' sein – artificis