1 回答

TA貢獻(xiàn)1891條經(jīng)驗(yàn) 獲得超3個(gè)贊
您基本上是從自動分配的標(biāo)識符切換到手動定義的標(biāo)識符,這在 JPA 和 Spring Data 級別上都會產(chǎn)生一些后果。
數(shù)據(jù)庫操作時(shí)序
在普通 JPA 級別,持久性提供程序不一定需要立即執(zhí)行單個(gè)插入,因?yàn)樗槐孬@取標(biāo)識符值。這就是為什么它通常會延遲語句的執(zhí)行,直到它需要刷新,這是在顯式調(diào)用 、EntityManager.flush()
查詢執(zhí)行時(shí),因?yàn)檫@需要數(shù)據(jù)庫中的數(shù)據(jù)是最新的以提供正確的結(jié)果或事務(wù)提交。
Spring Data JPA 存儲庫在調(diào)用save(…)
.?但是,如果您在依次注釋為的方法中調(diào)用存儲庫@Transactional
,則在離開該方法之前可能不會發(fā)生數(shù)據(jù)庫交互。
EntityManager.persist(…)
對比。….merge(…)
JPA 要求EntityManager
客戶端代碼區(qū)分是持久保留全新實(shí)體還是對現(xiàn)有實(shí)體應(yīng)用更改。Spring Data 存儲庫希望使客戶端代碼免于處理這種區(qū)別,因?yàn)闃I(yè)務(wù)代碼不應(yīng)因該實(shí)現(xiàn)細(xì)節(jié)而過載。這意味著 Spring Data 必須以某種方式將新實(shí)體與現(xiàn)有實(shí)體區(qū)分開來。
在手動標(biāo)識符的情況下,默認(rèn)檢查標(biāo)識符屬性的null
值將不起作用,因?yàn)樵搶傩杂肋h(yuǎn)不會被null
定義。標(biāo)準(zhǔn)模式是調(diào)整實(shí)體以實(shí)現(xiàn)Persistable
并保留瞬態(tài) is-new-標(biāo)志,并使用實(shí)體回調(diào)注釋來翻轉(zhuǎn)標(biāo)志。
@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被聲明為暫時(shí)的,以便它不會被持久化。該類型實(shí)現(xiàn)Persistable以便存儲庫save(…)方法的 Spring Data JPA 實(shí)現(xiàn)將使用它。上面的代碼會導(dǎo)致使用new將標(biāo)志設(shè)置為 的用戶代碼創(chuàng)建實(shí)體true,但任何類型的數(shù)據(jù)庫交互(保存或加載)都會將該實(shí)體轉(zhuǎn)換為現(xiàn)有實(shí)體,因此,除了所有后續(xù)操作外,這將首先save(…)觸發(fā)。EntityManager.persist(…)….merge(…)
我借此機(jī)會創(chuàng)建了DATAJPA-1600并將此描述的摘要添加到參考文檔中。
添加回答
舉報(bào)