我收到以下錯誤之前保存的瞬態的實例時,我節省使用Hibernate對象引用一個未保存的瞬態的實例 - 沖洗
object references an unsaved transient instance - save the transient instance before flushing
我收到以下錯誤之前保存的瞬態的實例時,我節省使用Hibernate對象引用一個未保存的瞬態的實例 - 沖洗
object references an unsaved transient instance - save the transient instance before flushing
對象應該包括cascade="all"
(如果使用XML)或cascade=CascadeType.ALL
(如果使用註釋)在你的收藏映射上。
發生這種情況是因爲您的實體中有一個集合,並且該集合中有一個或多個項目不存在於數據庫中。通過指定上述選項,您可以告訴hibernate在保存它們的父級時將它們保存到數據庫。
這不是隱含的嗎?你不會總是希望Hibernate保存它們嗎? – 2010-04-12 18:27:42
@馬庫斯 - 不,事實並非如此。你可能想要手動處理它們。 – Bozho 2010-04-12 20:27:30
Bozho是對的。我遇到過我想要手動管理的集合,因爲它們的大小,或者因爲業務規則不允許同時保存集合中的所有對象。 – 2010-11-19 00:35:05
這不是錯誤的唯一原因。我剛剛在我的編碼中遇到了一個錯字,我相信它會設置一個已經保存的實體的值。
X x2 = new X();
x.setXid(memberid); // Error happened here - x was a previous global entity I created earlier
Y.setX(x2);
我恰好找到發現錯誤哪個變量造成的錯誤(在這種情況下String xid
)。我在整個代碼塊周圍使用了一個catch
,這些代碼保存了實體並打印了這些痕跡。
{
code block that performed the operation
} catch (Exception e) {
e.printStackTrace(); // put a break-point here and inspect the 'e'
return ERROR;
}
與我的問題類似。最後,當我在本地重新加載實體時,設置屬性,然後保存,它工作正常。 – CsBalazsHungary 2014-11-26 12:43:27
我相信這可能只是重複的答案,但我只想澄清,我得到這個在@OneToOne
映射以及一個@OneToMany
。在這兩種情況下,事實上,我添加到Parent
的Child
對象尚未保存在數據庫中。因此,當我將Child
添加到Parent
,然後保存Parent
時,Hibernate在保存父節點時會丟棄"object references an unsaved transient instance - save the transient instance before flushing"
消息。
在cascade = {CascadeType.ALL}
上加上Parent's
參考Child
解決了這兩種情況下的問題。這節省了Child
和Parent
。
對不起,任何重複的答案,只是想進一步澄清爲人。
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
return performanceLog;
}
或者,如果你想用最少的「權力」(例如,如果你不想級聯刪除),以達到你想要什麼,用
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
...
@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
這應該是被接受的答案。 CascadeType.ALL太寬泛 – lilalinux 2016-09-15 07:48:12
從Hibernate 5.2.8開始,似乎無法通過JPA批註實現相同的效果。例如,'@ManyToMany(cascade = {PERSIST,MERGE,REFRESH,DETACH})'(除REMOVE之外的所有)不會像Hibernate的'CascadeType.SAVE_UPDATE'那樣級聯更新。 – 2017-03-16 12:53:43
保存對象時,會出現這種情況當Hibernate認爲它需要保存一個與正在保存的對象相關聯的對象時。
我有這個問題,並不想保存對引用對象的更改,所以我想級聯類型爲NONE。
訣竅是確保引用對象中的ID和VERSION被設置,以便Hibernate不會認爲引用的對象是需要保存的新對象。這對我有效。
查看要保存的類中的所有關係以計算關聯對象(以及關聯對象的關聯對象),並確保在對象樹的所有對象中都設置了ID和VERSION。
對於我來說,當持久化一個實體時,在該實體中數據庫中的現有記錄對於使用@Version註釋的字段具有NULL值(用於樂觀鎖定)。將數據庫中的NULL值更新爲0可以糾正此問題。
謝謝你!這是我遇到的問題。 – 2015-12-03 01:00:28
這應該是一個新問題,它應該被添加爲一個錯誤,至少是誤導性的例外。這原來是我的問題的原因。 – BML 2017-09-12 19:08:13
在我的情況下,它是通過在雙向關係的@ManyToOne
側沒有CascadeType
造成的。更確切地說,我在@OneToMany
一側有CascadeType.ALL
,在@ManyToOne
沒有。將CascadeType.ALL
添加到@ManyToOne
解決了問題。 一一對多側:
@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true)
private Set<GlobalConfigScope>gcScopeSet;
多對一一側(導致問題)
@ManyToOne
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
多對一一個(通過添加CascadeType.PERSIST
固定)
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
我得到這個錯誤,當我使用
getSession().save(object)
,但它沒有問題的作品,當我使用其他
getSession().saveOrUpdate(object)
一個可能的原因是:在我的情況,我試圖拯救父母,一個全新的實體之前救孩子。
的代碼是這樣的一個User.java模型:
this.lastName = lastName;
this.isAdmin = isAdmin;
this.accountStatus = "Active";
this.setNewPassword(password);
this.timeJoin = new Date();
create();
的setNewPassword()方法創建一個PasswordHistory記錄,並將其添加到歷史收集用戶。由於create()語句還沒有被父執行,所以它試圖保存到尚未創建的實體的集合中。我需要做的就是在調用create()之後移動setNewPassword()調用。
this.lastName = lastName;
this.isAdmin = isAdmin;
this.accountStatus = "Active";
this.timeJoin = new Date();
create();
this.setNewPassword(password);
要添加我的2美分,我得到了同樣的問題,當我米意外發送null
,作爲標識。下面的代碼描述了我的場景(並且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);
這裏I m所現有的部門ID設置爲一個新員工的實例,而不首先獲得該部門實體,因爲我不希望另一個選擇查詢開火。
在某些情況下,deptId
PKID將作爲null
來自調用方法,我會得到相同的錯誤。
所以,觀看null
值PK ID解決這一問題的
簡單的方法就是保存兩個實體。 先保存子實體,然後保存父實體。 因爲父實體依賴於子實體的外鍵值。
下面一個簡單的考試,一個關係
insert into Department (name, numOfemp, Depno) values (?, ?, ?)
Hibernate: insert into Employee (SSN, dep_Depno, firstName, lastName, middleName, empno) values (?, ?, ?, ?, ?, ?)
Session session=sf.openSession();
session.beginTransaction();
session.save(dep);
session.save(emp);
這是對子實體擁有FK值並取決於父項,因此您需要先保存父項!在代碼塊中你是對的。 – 2017-12-17 17:44:25
所有其他好的答案旁邊,如果你使用merge
堅持一個對象時,不慎忘記在父類中使用對象的合併引用這可能發生。考慮下面的例子
merge(A);
B.setA(A);
persist(B);
在這種情況下,您合併A
,但忘了用的A
合併對象。要解決這個問題,你必須像這樣重寫代碼。
A=merge(A);//difference is here
B.setA(A);
persist(B);
還有另外一種可能會導致hibernate出現此錯誤。您可以將未保存的對象A
的引用設置爲附屬實體B
並希望保留對象C
。即使在這種情況下,你也會得到上述錯誤。
直到你真的必須使用Cascade.All
。 Role
和Permission
有雙向manyToMany
的關係。然後下面的代碼將工作正常
Permission p = new Permission();
p.setName("help");
Permission p2 = new Permission();
p2.setName("self_info");
p = (Permission)crudRepository.save(p); // returned p has id filled in.
p2 = (Permission)crudRepository.save(p2); // so does p2.
Role role = new Role();
role.setAvailable(true);
role.setDescription("a test role");
role.setRole("admin");
List<Permission> pList = new ArrayList<Permission>();
pList.add(p);
pList.add(p2);
role.setPermissions(pList);
crudRepository.save(role);
而如果對象只是一個「新」的一個,那麼它會拋出相同的錯誤。
是100%正確的,Cascade.All是懶惰的解決方案,只有在需要時才應用。首先,如果實體已經存在,檢查它是否加載到當前實體管理器中,如果沒有加載它。 – 2017-03-03 16:43:28
錯誤的一個可能的原因是沒有設置父實體的值;例如,對於一個部門,員工的關係,你必須爲了修正這個錯誤,寫這篇文章:
Department dept = (Department)session.load(Department.class, dept_code); // dept_code is from the jsp form which you get in the controller with @RequestParam String department
employee.setDepartment(dept);
有此錯誤其他一些可能性也在增加頁面或編輯頁面的這麼多的可能性。在我的情況下,我試圖挽救一個對象AdvanceSalary。問題是,在編輯AdvanceSalary employee.employee_id爲空因爲編輯時我沒有設置employee.employee_id。我做了一個隱藏的領域並設置它。我的代碼工作得很好。
@Entity(name = "ic_advance_salary")
@Table(name = "ic_advance_salary")
public class AdvanceSalary extends BaseDO{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "employee_id", nullable = false)
private Employee employee;
@Column(name = "employee_id", insertable=false, updatable=false)
@NotNull(message="Please enter employee Id")
private Long employee_id;
@Column(name = "advance_date")
@DateTimeFormat(pattern = "dd-MMM-yyyy")
@NotNull(message="Please enter advance date")
private Date advance_date;
@Column(name = "amount")
@NotNull(message="Please enter Paid Amount")
private Double amount;
@Column(name = "cheque_date")
@DateTimeFormat(pattern = "dd-MMM-yyyy")
private Date cheque_date;
@Column(name = "cheque_no")
private String cheque_no;
@Column(name = "remarks")
private String remarks;
public AdvanceSalary() {
}
public AdvanceSalary(Integer advance_salary_id) {
this.id = advance_salary_id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public Long getEmployee_id() {
return employee_id;
}
public void setEmployee_id(Long employee_id) {
this.employee_id = employee_id;
}
}
如果你使用Spring數據JPA那麼除了@Transactional
註釋爲您服務的實施將解決這一問題。
我遇到了這個異常,當我沒有堅持父對象,但我救了孩子。爲了解決這個問題,在同一個會話中,我堅持使用子對象和父對象,並在父對象上使用CascadeType.ALL。
爲了完整起見:一個
org.hibernate.TransientPropertyValueException
有消息
object references an unsaved transient instance - save the transient instance before flushing
當您嘗試堅持/帶至這恰好是
另一個實體的引用合併的實體
也將發生分離。
在希望的情況下是這個錯誤?是否有或沒有瞬變變量? – vijay 2017-10-13 12:06:54