2013-03-19 44 views
13

Mam relację wiele-do-jednego, że chcę być pustych:Nie można uczynić związek @ManyToOne pustych

@ManyToOne(optional = true) 
@JoinColumn(name = "customer_id", nullable = true) 
private Customer customer; 

Niestety, JPA utrzymuje ustawienie kolumny w mojej bazy danych jako NOT NULL. Czy ktoś może to wyjaśnić? Czy istnieje sposób, aby to zadziałało? Zauważ, że używam JBoss 7, JPA 2.0 z Hibernate jako dostawca trwałości i bazy danych PostgreSQL 9.1.

EDIT:

znalazłem przyczynę mojego problemu. Widocznie to jest ze względu na sposób, w jaki zdefiniowano klucza podstawowego w wymienionej jednostce Customer:

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

Wydaje się, że za pomocą @Column(columnDefinition="serial") na klucz podstawowy automatycznie ustawia zagranicznych klucze odwołujące się do NOT NULL w bazie danych. Czy jest to rzeczywiście oczekiwane zachowanie podczas określania typu kolumny jako serial? Czy istnieje obejście umożliwiające włączanie zerowych kluczy obcych w tym przypadku?

Z góry dziękuję.

Odpowiedz

9

Znalazłem rozwiązanie mojego problemu. Sposób, w jaki klucz podstawowy jest zdefiniowany w jednostce Customer jest w porządku, problem znajduje się w deklaracji klucza obcego. Powinna ona zostać uznana za tak:

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

Rzeczywiście, jeśli atrybut columnDefinition="integer" pomija klucz będzie zagraniczny domyślnie ustawiony jako kolumny źródłowe: nie null szeregowej z własnej kolejności. Nie jest to oczywiście tym, czego chcemy, ponieważ chcemy po prostu odwołać się do automatycznie zwiększanego identyfikatora, a nie do nowego.

Poza tym wydaje się, że atrybut name=customer_id jest również wymagany, co zaobserwowałem podczas wykonywania niektórych testów. W przeciwnym razie kolumna klucza obcego będzie nadal ustawiona jako kolumna źródłowa. To dziwne zachowanie w mojej opinii. Komentarze lub dodatkowe informacje, aby to wyjaśnić, są mile widziane!

Wreszcie, zaletą tego rozwiązania jest to, że identyfikator jest generowany przez bazę danych (nie przez JPA), a zatem nie musimy się o to martwić podczas ręcznego wprowadzania danych lub za pomocą skryptów, które często mają miejsce podczas migracji lub konserwacji danych .

0

To bardzo dziwne.

W JPA parametr zerowy jest domyślnie prawdziwy. Używam tego rodzaju konfiguracji przez cały czas i działa dobrze. Jeśli spróbujesz uratować byt, powinno to się udać.

Czy próbowałeś usunąć tabelę utworzoną dla tej relacji? Może masz starszą tabelę z tą kolumną?

A może powinieneś spróbować znaleźć rozwiązanie na innych fragmentach kodu, ponieważ jest to właściwa konfiguracja.

Uwaga: Próbowałem tej konfiguracji w PostgreSQL z JPA2 i Hibernate.

EDIT

W takim przypadku może można spróbować nieco inną definicję klucza podstawowego.

Na przykład można użyć definicji tak:

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

i PostgreSQL wygeneruje

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

Jeśli jest wystarczająco dobre, możesz spróbować tego rozwiązania.

+0

to rzeczywiście rozwiązanie mam rozpatrywane. Niestety nie pozwala to na generowanie ID z samej bazy danych i jest to funkcja potrzebna przy ręcznym wprowadzaniu danych (na przykład przy użyciu hibernacji import.sql). Na szczęście chyba znajdę rozwiązanie. Właśnie robię testy i jeśli to się uda, opublikuję to rozwiązanie. Dzięki za pomoc. – vcattin

7

natknąłem ten problem, ale udało mi się rozwiązać to w ten sposób:

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

Może problem wyłonił wykazania @ManyToOne(optional = true)

+6

'nullable = false' ?? "false"? Dlaczego "false", a nie "true"? – Andremoniy

+0

zdecydowanie powinno być 'nullable = true' – artificis