2017-03-10 49 views
0

我有一個用戶實體,它使用用戶提供的電子郵件地址作爲主鍵而不是自動生成的值。這意味着當調用JpaRepository的保存方法時,主鍵值是非空彈簧數據JPA不允許實體在主鍵不爲空時被保留

春數據JPA documentation2.2.1節表2.2說以下內容:

缺省時,Spring數據JPA檢查給定 的實體的ID屬性。如果Id屬性爲空,則該實體將被假定爲 新的,否則不是新的。

此行爲阻止將新的訂購者實體持久保存到數據庫。

+4

它不應該。由於回購看到ID存在於輸入實體中,它將在內部調用'EntityManager.merge()',它仍應該保存您的實體。你只需要記住把'repository.save()'的返回值作爲被管實體 –

+0

@AdrianShum你是對的。它現在有效。但是,沒有檢測到重複項目。如果我嘗試保存同一個實體兩次,第二次它不會像我使用自動生成的密鑰一樣給出重複的異常。相同的實體更新,這不是我想要的。 – Amit

回答

0

The same table告訴您如何自定義該行爲。

要麼讓您的實體執行Persistable並覆蓋isNew,要麼提供EntityInformation的自定義實現。

+0

我知道isNew()方法。我可以調用findByEmail()並檢查實體是否存在。但是這需要額外的數據庫操作,我希望避免。 – Amit

+0

你是說你不知道如何確定你的實體是否是新的,但希望Spring Data能夠實現它嗎?這太恐懼了。 –

+0

在我之前對您發表評論之後,我想出瞭如何使用電子郵件ID作爲密鑰。你可以參考我的評論以上@AdrianShum。現在的問題是保存也更新實體,而不是給出重複的異常 – Amit

0

當談到決定如何選擇實體的主鍵時,我們有兩個選擇。 1.使用Spring 提供的自動生成的密鑰2.使用自定義主鍵,例如電子郵件地址。

自動生成的密鑰更易於使用。當堅持實體時,Spring注意到id字段爲空,並得出結論:這是一個新的實體被持久化。一個新的自動生成的值被分配給id字段,並且該實體被持久化。但是,如果您要確保具有相同電子郵件地址的兩個實體未被保留,請記住使用@Column(unique="true")註釋電子郵件字段。由於電子郵件字段的唯一限制,檢測重複郵件也很容易。

但是,有時您不想使用自動生成的密鑰,因爲您可能希望使用用戶提供的電子郵件地址作爲密鑰。這種方法沒有問題。用@Id標記實體中的電子郵件字段。就這樣。但是,重複檢測是不可能的。如果多次接收到創建具有相同電子郵件地址的實體的請求,則每次都會更新同一個實體,即每次都會執行EntityManager.merge()。違反約束的異常將不會被引發。回想一下,Spring總是檢查主鍵字段是否爲空,以決定是創建新實體還是合併到現有實體中。

相關問題