[英]update and return data in spring data JPA
出於並發目的,我需要在從 AVAILABLE 池中進行選擇時將數據庫列的狀態更新為 USED。
我正在考慮嘗試@Modifying
和@Query
(根據 where 子句更新狀態的查詢)
一切都很好,但這是一個更新查詢,因此它不會返回更新的數據。
那么,是否可以在 spring 數據中更新並返回一行,以便先讀取該行的人可以獨占使用它。
我的更新查詢類似於UPDATE MyObject o SET o.state = 'USED' WHERE o.id = (select min(id) from MyObject a where a.state='AVAILABLE')
,所以基本上最低的可用 id 將被標記使用。 有一個鎖定選項,但這些需要特殊處理,如果另一個線程發生異常,則重試,這在我的場景中不被批准
我建議使用多個事務加上樂觀鎖。 確保您的實體有一個用@Version
注釋的屬性。
在第一個事務中加載實體,將其標記為USED
,關閉事務。
這將刷新並提交更改,並確保在此期間沒有其他人觸及該實體。
在第二個事務中,您無法對實體執行任何操作。
對於這些小事務,我發現將它們移到單獨的方法中很笨拙,因此我可以使用@Transactional
。 因此,我改用TransactionTemplate
。
您需要明確聲明一個事務,以避免其他事務在提交之前能夠讀取所涉及的值。 允許它的最佳性能級別是READ_COMMITED ,它不允許來自其他事務的臟讀(適合您的情況)。 所以代碼看起來像這樣:
回購:
@Repository
public interface MyObjectRepository extends JpaRepository<MyObject, Long> {
@Modifying
@Query("UPDATE MyObject o SET o.state = 'USED' WHERE o.id = :id")
void lockObject(@Param("id") long id);
@Query("select min(id) from MyObject a where a.state='AVAILABLE'")
Integer minId();
}
服務:
@Transactional(isolation=Isolation.READ_COMMITTED)
public MyObject findFirstAvailable(){
Integer minId;
if ((minId = repo.minId()) != null){
repo.lockObject(minId);
return repo.findOne(minId);
}
return null;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.