亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用 Spring Data JPA 保存具有手動分配標識符的實體?

如何使用 Spring Data JPA 保存具有手動分配標識符的實體?

蕪湖不蕪 2023-06-21 14:48:33
我正在更新現有代碼,該代碼處理從一個表到同一數據庫中多個對象的復制或原始數據。以前,每種對象都有一個使用每個表的序列生成的 PK。像這樣的東西:@Id@Column(name = "id")@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;為了重用導入表中的現有 ID,我們刪除了某些實體的 generatedValue,如下所示:@Id@Column(name = "id")private Integer id;對于這個實體,我沒有更改我的 JpaRepository,如下所示:public interface EntityRepository extends JpaRepository<Entity, Integer> {    <S extends Entity> S save(S entity);}現在,我正在努力理解具有默認傳播和隔離級別的 spring 事務 (@Transactional) 中的以下行為:通過實體上的@GenerateValue,當我調用entityRepository.save(entity)時,我可以看到Hibernate顯示sql激活了一個插入請求被觸發(但是似乎只在緩存中,因為數據庫沒有改變)如果實體上沒有 @GeneratedValue,只會觸發一個選擇請求(不會嘗試插入)當我的實體(沒有生成的值)在一個或多個關系中映射到 MyOtherEntity(有生成的值)時,這是一個大問題。因此我有以下錯誤:ERROR: insert or update on table "t_other_entity" violates foreign key constraint "other_entity_entity"Détail : Key (entity_id)=(110) is not present in table "t_entity"似乎合法,因為尚未為實體發送插入,但為什么呢?同樣,如果我更改實體的 ID 并使用 @GeneratedValue,我不會收到任何錯誤。我正在使用 Spring Boot 1.5.12、Java 8 和 PostgreSQL 9
查看完整描述

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并將此描述的摘要添加到參考文檔中。


查看完整回答
反對 回復 2023-06-21
  • 1 回答
  • 0 關注
  • 179 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號