1 回答

TA貢獻1891條經驗 獲得超3個贊
您基本上是從自動分配的標識符切換到手動定義的標識符,這在 JPA 和 Spring Data 級別上都會產生一些后果。
數據庫操作時序
在普通 JPA 級別,持久性提供程序不一定需要立即執行單個插入,因為它不必獲取標識符值。這就是為什么它通常會延遲語句的執行,直到它需要刷新,這是在顯式調用 、EntityManager.flush()
查詢執行時,因為這需要數據庫中的數據是最新的以提供正確的結果或事務提交。
Spring Data JPA 存儲庫在調用save(…)
.?但是,如果您在依次注釋為的方法中調用存儲庫@Transactional
,則在離開該方法之前可能不會發生數據庫交互。
EntityManager.persist(…)
對比。….merge(…)
JPA 要求EntityManager
客戶端代碼區分是持久保留全新實體還是對現有實體應用更改。Spring Data 存儲庫希望使客戶端代碼免于處理這種區別,因為業務代碼不應因該實現細節而過載。這意味著 Spring Data 必須以某種方式將新實體與現有實體區分開來。
在手動標識符的情況下,默認檢查標識符屬性的null
值將不起作用,因為該屬性永遠不會被null
定義。標準模式是調整實體以實現Persistable
并保留瞬態 is-new-標志,并使用實體回調注釋來翻轉標志。
@MappedSuperclass
public abstract class AbstractEntity<ID extends SalespointIdentifier> implements Persistable<ID> {
? private @Transient boolean isNew = true;
? @Override
? public boolean isNew() {
? ? return isNew;
? }
? @PrePersist
? @PostLoad
? void markNotNew() {
? ? this.isNew = false;
? }
? // More code…
}
isNew被聲明為暫時的,以便它不會被持久化。該類型實現Persistable以便存儲庫save(…)方法的 Spring Data JPA 實現將使用它。上面的代碼會導致使用new將標志設置為 的用戶代碼創建實體true,但任何類型的數據庫交互(保存或加載)都會將該實體轉換為現有實體,因此,除了所有后續操作外,這將首先save(…)觸發。EntityManager.persist(…)….merge(…)
我借此機會創建了DATAJPA-1600并將此描述的摘要添加到參考文檔中。
添加回答
舉報