![](/img/trans.png)
[英]object references an unsaved transient instance - save the transient instance before flushing : Spring Data JPA
[英]Data was not saved: object references an unsaved transient instance - save the transient instance before flushing
我有一個包含兩個表User和Country的數據庫。 我想要關系,許多用戶可以屬於一個縣。 我使用以下模型類使用hibernate實現它:
@Entity (name = "user")
public class User {
@Id @GeneratedValue (strategy = GenerationType.IDENTITY)
private int userId;
private String username;
private String password;
@ManyToOne ()
@JoinColumn (name = "countryId")
private Country country;
//Getter & Setter
}
@Entity (name = "country")
public class Country {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private int countryId;
private String countryName;
//Getter & Setter
}
當我嘗試保存用戶對象時,我得到以下異常:
org.hibernate.HibernateException: Data was not saved: object references an unsaved transient instance - save the transient instance before flushing: com.kyrogaming.models.Country
我該如何解決這個問題?
在你告訴Hibernate關於這個新保存的對象引用的所有其他對象之前,你不能將東西保存到Hibernate。 所以在這種情況下,你告訴Hibernate一個User
,但沒有告訴它有關Country
。
您可以通過兩種方式解決此類問題。
手動
在保存User
之前調用session.save(country)
。
CascadeType的
您可以指定Hibernate這個關系應該使用CascadeType傳播一些操作。 在這種情況下,CascadeType.PERSIST將完成這項工作,CascadeType.ALL也是如此。
參考現有國家
根據您對@zerocool的響應,您有第二個問題,即當您有兩個具有相同Country
User
對象時,您不確定它是否是同一個 Country
。 為此,您必須從數據庫中獲取相應的Country
,在新用戶上設置它,然后保存User
。 然后,兩個User
對象將引用同一個Country
,而不僅僅是兩個碰巧具有相同名稱的Country
實例。 查看Criteria
API作為獲取現有實例的一種方法。
看起來像您的Country對象中添加的用戶看起來不在DB中。 您需要使用級聯來確保當國家/地區持久化時,所有不在數據中但與國家/地區相關聯的用戶也會被保留。
下面的代碼應該有幫助
@ManyToOne (cascade = CascadeType.ALL)
@JoinColumn (name = "countryId")
private Country country;
為了增加我的2美分,當我意外地發送null
作為ID時,我遇到了同樣的問題。 下面的代碼描述了我的場景(並且無論如何OP沒有提到任何特定場景) 。
Employee emp = new Employee();
emp.setDept(new Dept(deptId)); // -----> when deptId PKID is null, same error will be thrown
// calls to other setters...
em.persist(emp);
在這里,我將現有的部門ID設置為新的員工實例,而不是首先實際獲取部門實體,因為我不想要另一個選擇查詢。
在某些情況下, deptId
PKID即將為null
的調用方法而我會得到同樣的錯誤。
因此,請注意PK ID的null
值
這里給出的答案相同
我有同樣的問題。 在我的情況下,它出現了,因為查找表“country”具有countryId == 0和原始主鍵的現有記錄,我嘗試使用countryID == 0保存用戶。 將國家/地區的主鍵更改為Integer。 現在Hibernate可以識別新記錄。
有關使用包裝類作為主鍵的建議,請參閱此stackoverflow問題
它應該是CascadeType.Merge,在這種情況下,如果記錄已經存在,它將更新。
好吧,如果你已經給了
@ManyToOne ()
@JoinColumn (name = "countryId")
private Country country;
那個類的對象我的意思是國家需要先保存。
因為只有當該用戶的國家/地區可以使用該密鑰時,它才會允許用戶保存到數據庫中。 表示當且僅當該國家/地區存在於Country表中時,才允許用戶保存。
因此,您需要先將該國家/地區保存到表格中。
這是因為CASCADE TYPE
如果你放
@OneToOne(級聯= CascadeType.ALL)
你可以像這樣保存你的對象
user.setCountry(country);
session.save(user)
但如果你放
@OneToOne(cascade={
CascadeType.PERSIST,
CascadeType.REFRESH,
...
})
你需要像這樣保存你的對象
user.setCountry(country);
session.save(country)
session.save(user)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.