2016-06-21 115 views
0

我有2個實體(我刪除無用的字段):春天JPA保存現有的@OneToMany關係的實體

@Entity 
public class ApkPermissions { 
    @Id 
    @GeneratedValue 
    @JsonIgnore 
    private Long id; 

    @OneToMany 
    @Cascade({CascadeType.SAVE_UPDATE}) 
    private Collection<Permission> declaredPermissions; 
} 

@Entity 
public class Permission { 
    @Id 
    @GeneratedValue 
    @JsonIgnore 
    private Long id; 

    @Column(unique = true) 
    private String permissionName; 
} 

當我保存的ApkPermissions實體首次通過一個CrudRepository我沒有問題,但是當我保存另一個ApkPermissions與Permission表中已經存在的一些權限時,會引發一個異常,指出唯一密鑰違反permissionName。

我發現這個解決方案:

http://www.mkyong.com/hibernate/cascade-jpa-hibernate-annotation-common-mistake/

,似乎適合我的情況(是我目前的實現),但它不工作。

我收到以下錯誤信息:

could not execute statement; SQL [n/a]; constraint [UK_l3pmqryh8vgle52647itattb9]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 

從MySQL:

UNIQUE KEY `UK_l3pmqryh8vgle52647itattb9` (`permission_name`) 

臨時解決方法是retrive所有相應的權限從資源庫通過permissionName搜索。然後保存工作正常。 它在邏輯上是正確的,但我希望存在一個更簡單的過程...

+0

您能否包含異常消息的輸出? – 2016-06-21 20:25:56

+0

我做到了。請注意,現在我改變了關係爲@Pardeep建議 –

回答

0

在OneToMany映射,您的權限表將有一個額外的列將是一個外鍵指向您的ApkPermissions。 例如:

ApkPermission   Permission 
APK_ID | Name   Permission_ID | Name | APK_ID(FK) 
1  | APK1   1   | P1 | 1 
         2   | P2 | 1 

所以你不能點任何其他ApkPermission戰績相同的權限。假設,如果你想輸入2 | APK2在ApkPermission中,並且想要再次指向P1和P2。除非您在權限表中再次輸入P1和P2,否則無法使用一對多關係。這會產生重複。因此,您有兩個選項,您可以刪除唯一約束(在permissionName上),也可以將映射更改爲ManyToMany。

+0

你說得對,正確的關係是ManyToMany ... 但是當我保存一個已經存在於db中的聲明權限的ApkPermission時,問題依然存在。 –

+0

你試過manyToMany嗎?在這種情況下你將需要一個更多的連接表。新的條目將進入新的連接表。有很多示例available.With OneToMany,你必須插入新的記錄。否則它不會有任何意義。 –

+0

如果你還想繼續使用OneToMany(&不會被標準化),那麼你可以從permissionName中刪除唯一的約束,因爲你將會有重複。我建議試試ManyToMany。我想提到的一點是,如果主鍵爲空,則hibernate保存總是會進行插入查詢。在這種情況下,請使用saveOrUpdate。但是,如果你的記錄存在於數據庫中,那麼當你嘗試堅持它時,ID不應該爲空,否則它總會假定它是一個新記錄。 –