2012-01-23 92 views
19

我有用戶和地址分類如下:爲什麼@OneToOne允許重複關聯?

class User 
{ 
    ... 
    ... 
    @OneToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="addr_id") 
    private Address address; 
} 

class Address 
{ 
    ... 
    ... 
    @OneToOne(mappedBy="address") 
    private User user; 
} 

這裏我的假設是這個領域模型我一個地址,只有一個用戶關聯(user.addr_id應該是唯一的)。

但是,通過此域模型,我可以創建多個用戶並將它們關聯到相同的地址。

User u1 = new User(); 
//set data 
Address addr1 = new Address(); 
//set data 
u1.setAddress(addr1); 
... 
session.save(u1); 

- >這是用addr_id = 1創建一個地址記錄,並在addr_id = 1的用戶表中插入一個用戶記錄。精細。

再次,

User u2 = new User(); 
//set data 
Address addr1 = (Address) session.load(Address.class, 1); 
//set data 
u2.setAddress(addr1); 
... 
session.save(u2); 

- >這是創建第二用戶記錄和相關聯以與addr_id = 1現有地址,這是不希望的。

爲了防止出現這種情況,我可以使用@OneToOne(..)@ JoinColumn(name =「addr_id」,unique = true)。 但是使用@OneToOne而不是@ManyToOne(..,unique = true)會有什麼區別。

@OneToOne本身應該強加「唯一=真實」的條件..對吧?

-Siva

+0

我面臨同樣的問題。 'OneToOne'應該重命名爲'OneToOneOnEntityLevel'。同樣,'JpaRepository.save()'應該是'jpaRepository.saveOrMerge()'。這兩件事可能會導致數據庫級別的數據損壞。 –

回答

6

@OneToOne被註釋了Java來表示兩個類之間的關係的想法。如果這是@OneToMany,那麼我們會有一個集合。因此,閱讀註釋我們理解了實際​​情況,JPA運行時也理解這些。

在數據庫中執行一對一的實際治理 - 我們需要架構具有唯一性約束。 @JoinColumn表示如何在DatabaseSchema中顯示該關係。如果我們正在生成模式,這可能很有用。

但是在很多情況下,我們使用自下而上的工具從模式生成Java。在這種情況下,從Java角度來看,沒有實際需要Java註釋來反映數據庫約束。

智能編譯器可能會警告我們,如果我們的@JoinColumn的語義與@oneToOne不匹配,但我不確定當前的實現是否可以執行此操作。

4

OneToOne是描述對象模型的註釋。它說明協會的基數是什麼。 unique="true"是「模型到ddl」工具的一個指示,表明該列上應該有一個唯一的符合條件。您可以使用這樣的工具,但您也可以自由創建和維護數據庫模式。

無論您選擇做什麼,JPA引擎在每次修改OneToOne關聯時都不會進行查詢,以檢查基數是否受到尊重。它所做的只是假設代碼是正確的,並且數據庫中的唯一約束將確保基數得到尊重。