1.概述

在本快速教程中,我们将讨论在Spring Data JPA中为自定义查询方法和预定义存储库的CRUD方法启用事务锁, 我们还将查看不同的锁类型并设置事务锁超时。

2.锁类型

JPA定义了两种主要的锁类型,即悲观锁和乐观锁。

2.1悲观锁

当我们在事务中使用悲观锁并访问实体时,它将立即锁定。通过提交或回滚事务来释放锁。

2.2乐观锁

在乐观中,事务不会立即锁定实体。相反,事务通常会保存实体的状态,并为其分配版本号。

当我们尝试在不同的事务中更新实体的状态时,事务会在更新期间将保存的版本号与现有的版本号进行比较。

此时,如果版本号不同,则表示无法修改实体。如果存在活动事务,那么该事务将被回滚,并且底层JPA实现将抛出OptimisticLockException

除版本号方法外,我们还可以使用其他方法,如时间戳,哈希值计算或序列化校验和,具体取决于哪种方法最适合我们当前的开发环境。

3.在查询方法上启用事务锁

要获取实体的锁定,我们可以通过使用@Lock来注解目标查询方法, 并传递所需的锁定模式类型

锁定模式类型(Lock mode types)是锁定实体时要指定的枚举值。然后,将指定的锁定模式传递到数据库,以在实体对象上应用相应的锁定。

要在Spring Data JPA存储库的自定义查询方法上指定锁定,我们可以使用@Lock注解该方法并指定所需的锁定模式类型:

@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("SELECT c FROM Customer c WHERE c.orgId = ?1")
public List<Customer> fetchCustomersByOrgId(Long orgId);

要强制锁定预定义的存储库方法(如findAll或findById(id)),我们必须在存储库中声明方法并使用@Lock注解该方法:

@Lock(LockModeType.PESSIMISTIC_READ)
public Optional<Customer> findById(Long customerId);

当显式启用锁并且没有活动事务时,底层JPA实现将抛出TransactionRequiredException

如果无法授予锁并且锁冲突不会导致事务回滚,则JPA会抛出LockTimeoutException。但它不标记回滚的活动事务。

4.设置事务锁定超时

使用悲观锁时,数据库将尝试立即锁定实体。当无法立即获取锁定时,底层JPA实现会抛出LockTimeoutException。为避免此类异常,我们可以指定锁超时时间。

在Spring Data JPA中,可以使用@QueryHints指定锁定超时时间:

@Lock(LockModeType.PESSIMISTIC_READ)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "3000")})
public Optional<Customer> findById(Long customerId);

有关在不同范围设置锁定超时提示的更多详细信息,请参见ObjectDB文章

5.结论

在本教程中,我们学习了不同类型的事务锁定模式,以及如何在Spring Data JPA中启用事务锁,并简单介绍了如何设置锁定超时。

在正确的位置应用正确的事务锁,可以帮助维护高并发情况下应用程序中数据完整性。

当交易需要严格遵守ACID规则时,我们应该使用悲观锁。当我们需要允许多个并发读取以及在应用程序上下文中可接受的最终一致性时,应该应用乐观锁。

当然,可以在Github上找到悲观锁和乐观锁的示例代码。

原文:https://www.baeldung.com/java-jpa-transaction-locks

作者:baeldung

译者:Leesen

Spring Data JPA 事务锁的更多相关文章

  1. Spring Data JPA 事务

    Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套 JPA 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常 ...

  2. springboot深入学习(五)-----spring data、事务

    spring data项目是spring解决数据访问问题的一系列解决方案,包含了大量关系型数据库以及非关系型数据库的访问解决方案. 一.spring data jpa 1.简介 jpa是一套规范,不提 ...

  3. spring spring data jpa save操作事务

    整合spring spring data jpa的时候,在save方法上加了@Transactional注解.此时调用springdatajpa save方法并不会真的把数据提交给数据库,而是缓存起来 ...

  4. Spring data Jpa,Mybatis,读写锁,@Lock 使用

    Spring data jpa 支持注解式的读写锁(悲观锁),实际上这个东西硬编码也简单,但是基于Jpa 命名方式定义的Sql,只能用注解添加支持读写锁了, 不了解读写锁的可以点这里 mysql读写锁 ...

  5. 解决neo4j @Transactional 与Spring data jpa @Transactional 冲突问题,@CreatedBy,@CreatedDate,@LastModifiedBy,@LastModifiedDate,以及解决@Version失效问题

    之前mybatis特别流行,所以前几个项目都是用@SelectProvider,@InsertProvider,@UpdateProvider,@DeleteProvider 加反射泛型封装了一些通用 ...

  6. Spring data jpa 复杂动态查询方式总结

    一.Spring data jpa 简介 首先我并不推荐使用jpa作为ORM框架,毕竟对于负责查询的时候还是不太灵活,还是建议使用mybatis,自己写sql比较好.但是如果公司用这个就没办法了,可以 ...

  7. 一文搞定 Spring Data JPA

    Spring Data JPA 是在 JPA 规范的基础上进行进一步封装的产物,和之前的 JDBC.slf4j 这些一样,只定义了一系列的接口.具体在使用的过程中,一般接入的是 Hibernate 的 ...

  8. 快速搭建springmvc+spring data jpa工程

    一.前言 这里简单讲述一下如何快速使用springmvc和spring data jpa搭建后台开发工程,并提供了一个简单的demo作为参考. 二.创建maven工程 http://www.cnblo ...

  9. spring boot(五):spring data jpa的使用

    在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...

随机推荐

  1. 【转】Nodejs学习笔记(二)--- 模块

    目录 简介及资料 自定义模块 创建一个自定义模块 调用自定义模块 exports和module.exports 区别 exports和module.exports 覆盖 其它... 简介及资料 通过N ...

  2. L#中 int.TryParse 有问题

    今天发现了一个 L# 的异常..因此记录一下 List<string> strList = new List<string>(); ; i<; ++i) { ; j< ...

  3. MAC电脑安装Mysql服务器和Navicat for mysql客户端

    1.下载链接 Navicat for mysql客户端 链接: https://pan.baidu.com/s/1dGbzgbR 密码: i43g Mysql服务器 链接: https://pan.b ...

  4. Why Namespace?

    上一节我们讨论了 Neutron 将虚拟 router 放置到 namespace 中实现了不同 subnet 之间的路由.今天探讨为什么要用 namespace 封装 router? 回顾一下前面的 ...

  5. Render 使用

    Page页面文件,重新Render 方法,目的是把页面的ViewState信息放在最后,利于页面展示速度和SEO优化. Render方法对于重新Html控件还是很好用的. private static ...

  6. Educational Codeforces Round 37 A B C D E F

    A. water the garden Code #include <bits/stdc++.h> #define maxn 210 using namespace std; typede ...

  7. python3字符串操作总结

    字符串截取  >>>s = 'hello' >>>s[0:3] 'he' >>>s[:] #截取全部字符 'hello' 消除空格及特殊符号 s. ...

  8. LeetCode OJ-- LRU Cache ***@

    https://oj.leetcode.com/problems/lru-cache/ 涨姿势的一道题,相当于实现一种数据结构,实现最近最少使用数据结构. // 用来记录 前后节点都是什么 类似链表上 ...

  9. 洛谷 P1478 陶陶摘苹果(升级版)【贪心/结构体排序/可用01背包待补】

    [链接]:https://www.luogu.org/problemnew/show/P1478 题目描述 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他 ...

  10. getServletConfig().getInitParameter("count1") java.lang.NullPointerException

    通常在doget中 System.out.println(getServletConfig()); System.out.println(getServletConfig().getInitParam ...