2013-03-19 81 views
13

我有很多一對一的關係,我想可空:不能使@ManyToOne關係可空

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

不幸的是,JPA不斷設置我的數據庫中列NOT NULL。任何人都可以解釋嗎?有沒有辦法讓它工作?請注意,我使用JBoss 7,JPA 2.0和Hibernate作爲持久性提供者和PostgreSQL 9.1數據庫。

編輯

,我發現我的問題的原因。顯然,這是由於我的方式定義在引用的實體Customer主鍵:

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

看來,使用@Column(columnDefinition="serial")主鍵自動設置外鍵在數據庫中它引用到NOT NULL。當將列類型指定爲serial時,這真的是預期的行爲嗎?在這種情況下是否有一種解決方法來啓用可空的外鍵?

預先感謝您。

回答

9

我找到了我的問題的解決方案。主鍵在實體Customer中的定義方式沒問題,問題在於外鍵聲明。應該聲明如下:

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

事實上,如果省略該屬性columnDefinition="integer"默認的外鍵將被設置爲源列:非空系列都有自己的序列。這當然不是我們想要的,因爲我們只是想引用自動遞增的ID,而不是創建一個新ID。

此外,似乎屬性name=customer_id也是需要的,因爲我在執行一些測試時觀察到。否則,外鍵列仍將被設置爲源列。我認爲這是一種奇怪的行爲。歡迎發表評論或其他信息以便澄清此問題!

最後,這個解決方案的優點是ID由數據庫生成(不是由JPA生成),因此當手動插入數據或通過經常發生在數據遷移或維護中的腳本時,我們不必擔心。

0

這很奇怪。

在JPA中,可空參數默認爲true。我一直使用這種配置,它工作正常。如果你試圖保存實體,它應該是成功的。

您是否嘗試刪除爲此關係創建的表?也許你有那個列的遺留表?

或者,您應該嘗試在其他代碼塊上找到解決方案,因爲這是正確的配置。

注:我已經在PostgreSQL上用JPA2和Hibernate嘗試過這種配置。

編輯

在這種情況下,也許你可以嘗試主鍵的一點點不同的定義。

例如,你可以使用定義是這樣的:

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

和PostgreSQL將產生

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

如果這是不夠好,你可以嘗試此解決方案。

+0

這確實是我考慮的解決方案應運而生。不幸的是,這並不支持從數據庫本身生成ID,而且這是手動插入數據時需要的功能(例如使用hibernate的import.sql)。幸運的是,我想我即將找到解決方案。我只是在做一些測試,如果成功,我會發布解決方案。謝謝你的幫助。 – vcattin 2013-03-23 23:34:19

7

我遇到了這個問題,但我還是能夠解決這樣說:

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

也許問題的聲明@ManyToOne(optional = true)

+6

'nullable = false'? 'FALSE'?爲什麼是'假',而不是'真'? – Andremoniy 2015-05-19 09:15:08

+0

絕對應該是'nullable = true' – artificis 2016-11-16 14:28:11