国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

香港云服务器
服務器之家 - 編程語言 - Java教程 - Spring Boot2+JPA之悲觀鎖和樂觀鎖實戰(zhàn)教程

Spring Boot2+JPA之悲觀鎖和樂觀鎖實戰(zhàn)教程

2022-02-20 12:08Moshow鄭鍇 Java教程

這篇文章主要介紹了Spring Boot2+JPA之悲觀鎖和樂觀鎖實戰(zhàn)教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

前言

大量的請求,或者同時的操作,容易導致系統(tǒng)在業(yè)務上發(fā)生并發(fā)的問題. 通常講到并發(fā),解決方案無非就是前端限制重復提交,后臺進行悲觀鎖或者樂觀鎖限制.

悲觀鎖與并發(fā)

悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時候都認為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會block直到解鎖,可以理解為獨占鎖。在java中synchronized和ReentrantLock重入鎖等鎖就是悲觀鎖,數(shù)據(jù)庫中表鎖、行鎖、讀寫鎖等也是悲觀鎖。

利用SQL的for update解決并發(fā)問題

行鎖就是操作數(shù)據(jù)的時候把這一行數(shù)據(jù)鎖住,其他線程想要讀寫必須等待,但同一個表的其他數(shù)據(jù)還是能被其他線程操作的。只要在需要查詢的sql后面加上for update,就能鎖住查詢的行,特別要注意查詢條件必須要是索引列,如果不是索引就會變成表鎖,把整個表都鎖住。

?
1
2
3
4
public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Query(value = "select * from article a where a.id = :id for update", nativeQuery = true)
    Optional<Article> findArticleForUpdate(Long id);
}

利用JPA的@Lock行鎖注解解決并發(fā)問題

如果說for update的做法太原始,那么JPA有提供一個更加優(yōu)雅的方法,就是@Lock注解 .

為Repository添加JPA的鎖方法,其中LockModeType.PESSIMISTIC_WRITE參數(shù)就是行鎖。

關于LockModeType這個類型,可以在這找到文檔 https://docs.oracle.com/javaee/7/api/javax/persistence/LockModeType.html

  • NONE: No lock.
  • OPTIMISTIC: Optimistic lock.
  • OPTIMISTIC_FORCE_INCREMENT: Optimistic lock, with version update.
  • PESSIMISTIC_FORCE_INCREMENT: Pessimistic write lock, with version update.
  • PESSIMISTIC_READ: Pessimistic read lock.
  • PESSIMISTIC_WRITE: Pessimistic write lock.
  • READ: Synonymous with OPTIMISTIC.
  • WRITE: Synonymous with OPTIMISTIC_FORCE_INCREMENT.
?
1
2
3
4
5
public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
    @Query("select a from Article a where a.id = :id")
    Optional<Article> findArticleWithPessimisticLock(Long id);
}

如果是@NameQuery,則可以

?
1
2
@NamedQuery(name="lockArticle",query="select a from Article a where a.id = :id",lockMode = PESSIMISTIC_READ)
public class Article

如果用entityManager的方式,則可以設置LocakMode:

?
1
2
3
4
Query query = entityManager.createQuery("from Article where articleId = :id");
query.setParameter("id", id);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
query.getResultList();

樂觀鎖與并發(fā)

樂觀鎖(Optimistic Lock),顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認為別人不會修改,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去修改。所以悲觀鎖是限制其他線程,而樂觀鎖是限制自己,雖然他的名字有鎖,但是實際上不算上鎖,通常為version版本號機制,還有CAS算法 .

利用version字段解決并發(fā)問題

版本號機制就是在數(shù)據(jù)庫中加一個字段version當作版本號。那么獲取Article的時候就會帶一個版本號,比如version=1,然后你對這個Article一波操作,操作完之后要插入到數(shù)據(jù)庫了。

校驗一下version版本號,發(fā)現(xiàn)在數(shù)據(jù)庫里對應Article記錄的version=2,這和我手里的版本不一樣啊,說明提交的Article不是最新的,那么就不能update到數(shù)據(jù)庫了,進行報錯把,這樣就避免了并發(fā)時數(shù)據(jù)沖突的問題。

?
1
2
3
4
5
public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Modifying
    @Query(value = "update article set content= :content, version = version + 1 where id = :id and version = :version", nativeQuery = true)
    int updateArticleWithVersion(Long id, String content, Long version);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
public void postComment(Long articleId, String content) {
 //get article
    Optional<Article> articleOptional = articleRepository.findById(articleId);
    //update with Optimistic Lock
    int count = articleRepository.updateArticleWithVersion(article.getId(), content, article.getVersion());
  
    if (count == 0) {
        throw new RuntimeException("更新數(shù)據(jù)失敗,請刷新重試");
    }else{
     articleRepository.save(article);
    }
}

利用JPA的@Version版本機制解決并發(fā)問題

有沒有更優(yōu)雅的方式? 當然,必須有,那就是JPA自帶的@Version方式實現(xiàn)樂觀鎖。

  • each entity class must have only one version attribute .每個實體類只能有一個@Version字段,不能多
  • it must be placed in the primary table for an entity mapped to several tables . 對于映射到多個表的實體,必須將其放置在主表中
  • type of a version attribute must be one of the following: int, Integer, long, Long, short, Short, java.sql.Timestamp ,

@Version支持的類型必須是以下類型:

  • int
  • Integer
  • long
  • Long
  • short
  • Short
  • java.sql.Timestamp

首先在Article實體類的version字段上加上@Version注解

?
1
2
3
4
5
6
7
8
9
@Data
@Entity
public class Article{
    @Id
    private Long id; 
  //...... 
    @Version
    private Integer version;
}
?
1
2
3
Article article = entityManager.find(Article.class, id);
entityManager.lock(article , LockModeType.OPTIMISTIC);
entityManager.refresh(article , LockModeType.READ);

什么時候用悲觀鎖或者樂觀鎖

悲觀鎖適合寫多讀少的場景。因為在使用的時候該線程會獨占這個資源,就適合用悲觀鎖,否則用戶只是瀏覽文章的話,用悲觀鎖就會經(jīng)常加鎖,增加了加鎖解鎖的資源消耗。

樂觀鎖適合寫少讀多的場景。由于樂觀鎖在發(fā)生沖突的時候會回滾或者重試,如果寫的請求量很大的話,就經(jīng)常發(fā)生沖突,結合事務會有經(jīng)常的回滾和重試,這樣對系統(tǒng)資源消耗也是非常大。

所以悲觀鎖和樂觀鎖沒有絕對的好壞,必須結合具體的業(yè)務情況來決定使用哪一種方式。另外在阿里巴巴開發(fā)手冊里也有提到:

如果每次訪問沖突概率小于 20%,推薦使用樂觀鎖,否則使用悲觀鎖。樂觀鎖的重試次數(shù)不得小于3次。

阿里巴巴建議以沖突概率20%這個數(shù)值作為分界線來決定使用樂觀鎖和悲觀鎖,雖然說這個數(shù)值不是絕對的,但是作為阿里巴巴各個大佬總結出來的也是一個很好的參考。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://zhengkai.blog.csdn.net/article/details/103086074

延伸 · 閱讀

精彩推薦
1148
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 午夜精品福利在线观看 | 中文字幕在线观看一区二区三区 | av天天干 | 精品久久久久久久久久久久久久 | 另类久久 | 国产一区二区三区在线免费 | 欧美精品一区二 | 久久综合中文字幕 | 久久久久久国产免费 | 国产色视频在线播放 | 久久久精品网 | 欧美日韩精品一区二区三区 | 日韩高清在线 | 欧美影视一区二区三区 | 国产一区二区三区视频 | 中文字幕日韩av | 欧美日韩高清一区 | 日本不卡免费一区二区三区综合久久 | 亚洲综合视频 | 91福利资源站| 91久久精品日日躁夜夜躁国产 | 亚洲视频一区在线播放 | 久久99精品久久久久婷婷暖91 | 伊人精品成人久久综合软件 | 欧美日韩国产一区 | 日本久久精品 | 亚洲国产成人在线 | 亚洲福利电影网 | 91综合网| 午夜精品久久久久久久星辰影院 | 欧洲精品久久久 | www.888www看片| 精品视频一区二区三区四区 | 日韩在线精品视频 | 日韩在线观看 | 久久精品电影 | 久久精品91久久久久久再现 | 国产精品久久国产精品 | 色视频网 | 久久久婷| 欧美一区二区三区 |