![](/img/trans.png)
[英]Getting “object references an unsaved transient instance” on already saved object
[英]object references an unsaved transient instance: how to flush or return saved object
我使用Spring 3.2.3和Hibernate 4.2.3和JDK 7。
我有一個簡單的實體:
@Entity
public class Language {
@Id
@GeneratedValue
private long id;
@Column(nullable = false, length = 3, unique = true)
private String code;
}
我使用@Service
注釋類和@Transactional
注釋方法保存了這個實體的實例,該方法使用DAO保存實體
sessionFactory.getCurrentSession().save(object);
之后我使用保存的 Language
實體來創建EntityX
,它在ManyToOne
關系中使用它...
lang=new Language();
// ...
languageService.saveLanguage(lang);
e=new EntityX();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);
和EntityX
定義為......
@Entity
public class EntityX {
@ManyToOne
@JoinColumn(nullable = false)
private Language language;
// ...
}
我總是得到例外
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: somepackage.Language
我嘗試在EntityX
與其他帖子中建議的Language
關系中使用一些級聯定義,但它沒有任何效果。
如果我通過使用一些HQL查詢通過其code
找到它來重新加載已保存的Language
實體,那么一切正常,但它遠離“好”。
不幸的是, org.hibernate.Session
的save(...)
方法沒有返回保存的對象。
有任何想法如何解決它?
你是用單個@Transactional
方法編寫代碼的嗎?
如果不是問題,那么在調用service方法之后,事務將被提交並且會話被清除。 當您嘗試保存實體時,在會話中未檢測到語言對象並將其作為臨時實例進行管理並給出錯誤。
如果您的代碼在單個事務下,您是否在保存實體之前嘗試flush()
以強制Hibernate存儲Language
到數據庫並為其分配有效的@Id
entifier?
畢竟 - 恕我直言 - 如果你有實體和語言的依賴,最好的選擇是:
@ManyToOne(cascade = CascadeType.ALL)
private Language language;
並將您的代碼更改為:
e=new EntityX();
Language lang = new Language();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);
並且您不需要在兩個步驟(語言+實體)中持久化實體; 將語言+實體作為單個項目管理
PS :org.hibernate.Session的save(...)方法不返回保存的對象,因為對象將保持不變(引用不會更改),只是對象屬性發生更改(如標記為@Id
,例如)!
編輯:
使對象持久化(我的意思是session.save())不會導致立即插入/更新; 沒有級聯提示Hibernate外觀不檢測EntityX和語言之間的依賴關系,並且在保存EntityX之前不執行語言的sql插入。
languageService.save(language)調用不執行session.flush(),因為你在同一個@Transactional
,沒有session.commit()沒有執行session.flush(),最好的選擇是語言對象仍被標記為瞬態。
您可以進行檢查:提取服務保存代碼(語言entityX)並將所有內容放在單個@Transactional
並檢查Hibernate是否仍然給您錯誤。
我最好的選擇仍然是在中間執行flush()或更改映射,別無他法
首先,如果code
字段是主鍵(或者您至少將它用作Hibernate的主要ID),請指定@Id:
@Id
@GeneratedValue(generator="assigned")
@Column(length = 3)
private String code;
不指定ID列可能會讓Hibernate有點困惑; 雖然不引用我的話。
如果save()
在此之后仍然無效,則可以使用merge()
:
Language lang = new Language("XYZ");
lang = session.merge(lange);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.