亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用JPA加鎖機制

發布時間:2021-10-15 11:17:33 來源:億速云 閱讀:471 作者:iii 欄目:開發技術

這篇文章主要介紹“如何使用JPA加鎖機制”,在日常操作中,相信很多人在如何使用JPA加鎖機制問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何使用JPA加鎖機制”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    JPA的加鎖機制有兩種,樂觀鎖和悲觀鎖。

    樂觀鎖:

    樂觀鎖的特點在于認為數據沖突或者更新丟失等情況是很少發生的.當發生的時候,拋出異常和回滾就足夠解決問題.

    悲觀鎖:

    悲觀鎖的邏輯在于認為每次數據操作都很有可能發生沖突,所以一開始就獲得記錄的鎖,再進行記錄的操作是解決問題的優先選擇.

    一 簡述悲觀鎖的用法

    悲觀鎖通常是SQL級別的,通過讀寫時先拿到鎖實現,在SQL語句中就會有體現.

    1.1 EntityManager 用法

    return em.createQuery(sql 語句).setLockMode(LockModeType.NONE).getResultList();
        //分解寫法大概是:
        Query query = getSession().createQuery(hql);
        query.setLockMode(LockModeType.NONE);

    EntityManager 是一個輔助類,createQuery后返回的就是一個Query對象,然后通過

    setLockMode設置鎖的級別即可.

    LockModeType 類型解釋
    LockMode.READ事務的隔離級別是Repeatable Read或Serializable時,請求讀取數據庫記錄時自動獲得
    LockMode.WRITE請求插入或更新數據庫記錄時自動獲得
    LockMode.OPTIMISTIC樂觀鎖
    LockMode.OPTIMISTIC_FORCE_INCREMENT樂觀鎖,通過version控制
    LockMode.PESSIMISTIC_READ與LockMode.PESSIMISTIC_WRITE相同
    LockMode.PESSIMISTIC_WRITE事務開始即獲得數據庫的鎖
    LockMode.PESSIMISTIC_FORCE_INCREMENT事務開始即設置version
    LockMode.NONE取消任何鎖,如事務結束后的所有對象,或執行了Session的update()、

    二 樂觀鎖的詳細用法

    樂觀鎖本篇的主要內容

    實體類是關鍵 , 樂觀鎖常用方法是通過version來控制 ,

    • 數據庫對應的表中需要有一個字段(名字隨意),字段類型設置成BigInt即可

    • 業務不對該字段進行控制,字段的控制交由系統處理

    • 每一次修改都會導致version遞增

    • 當出現同時獲得該記錄的對象且均需要修改時,當第一個已經提交事務,version字段發生改變,后面提交的事務發現version版本不對,則無法提交,拋出異常

    實體類(注意其中的@Version注解)

    @Entity
    public class User {
        @Id
        @GeneratedValue
        private Long id;
        private String username;
        private String userdesc;
        @Version
        private Long version;
        public User() {
        }
        public User(String username, String userdesc) {
            this.username = username;
            this.userdesc = userdesc;
        }
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getUserDesc() {
            return userdesc;
        }
        public void setUserDesc(String userdesc) {
            this.userdesc = userdesc;
        }
        public Long getVersion() {
            return version;
        }
        public void setVersion(Long version) {
            this.version = version;
        }
    }

    controller中通過sleep將線程沉睡,測試事務的提交性

    @RestController
    public class UserController {
        private Logger logger = LoggerFactory.getLogger(getClass());
        @Autowired
        UserService userService;
        @PostMapping("/changeone")
        @Transactional
        public String changeone() {
            User user = userService.findUser("gang");
            try {
                logger.info("修改1 before:user--{}--Versdion:{}", user.getUserDesc(), user.getVersion());
                Thread.sleep(25000);
                user.setUserDesc("修改1");
                logger.info("修改1 :user--{}--version:{}", user.getUserDesc(), user.getVersion());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                logger.info("eeeeeeeeeeeeee");
                e.printStackTrace();
            }
            return "true";
        }
        @PostMapping("/changetwo")
        @Transactional
        public String changetwo() {
            User user = userService.findUser("gang");
            try {
                logger.info("修改2 before:user--{}--version:{}", user.getUserDesc(), user.getVersion());
                Thread.sleep(30000);
                user.setUserDesc("修改2");
                logger.info("修改2:user--{}--version:{}", user.getUserDesc(), user.getVersion());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                logger.info("eeeeeeeeeeeeee");
                e.printStackTrace();
            }
            return "true";
        }
        @PostMapping("/changethree")
        @Transactional
        public String changethree() {
            User user = userService.findUser("gang");
            logger.info("修改3 before:user--{}--version:{}", user.getUserDesc(), user.getVersion());
            user.setUserDesc("修改3");
            logger.info("修改3 :user--{}--version:{}", user.getUserDesc(), user.getVersion());
            return "true";
        }
        @PostMapping("/newuser")
        @Transactional
        public String newuser() {
            logger.info("save user");
            User user = new User();
            user.setUserDesc("第一次創建");
            user.setUsername("gang");
            userService.saveUser(user);
            return "true";
        }
    }

    以及service及repository

    @Service
    public class UserService {
        @Autowired
        UserRepository userRepository;
        public User findUser(String username){
            return userRepository.findByUsername(username);
        }
        public void saveUser(User user){
            userRepository.save(user);
        }
    }
    UserRepository 
    public interface UserRepository extends JpaRepository<User,Long> {
        User findByUsername(String username);
    }

    總結

    使用很簡單,version是自動增長的,唯一的缺點是拋出的異常不易捕獲,捕獲的方法:

    @Resource
        private UserTransaction rtc;
         try {
                rtc.begin();
                User user = userService.findUser("gang");
                user .setDesc("異常捕獲");
                 rtc.commit();
            } catch (OptimisticLockException e) {
                throw new OptimisticLockException ();
            } catch (Exception e) {
                throw new Exception ();
            }

    注意其中的 rtc.begin(); 以及 rtc.commit();

    不同于@Transaction,這種是手動的提交方法

    到此,關于“如何使用JPA加鎖機制”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    jpa
    AI

    得荣县| 大安市| 平昌县| 积石山| 宜宾市| 中宁县| 乐至县| 乡城县| 梅州市| 措美县| 古浪县| 西昌市| 潮安县| 东莞市| 东乌珠穆沁旗| 上栗县| 萨嘎县| 贵州省| 泸州市| 扶沟县| 盈江县| 南召县| 万全县| 神木县| 通山县| 木兰县| 普安县| 磐石市| 澜沧| 铜陵市| 黔江区| 山阴县| 钟山县| 温宿县| 开化县| 济南市| 望城县| 普宁市| 义马市| 涟源市| 兰考县|