簡體   English   中英

更新和返回彈簧數據 JPA 中的數據

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM