如何指定查询的@Lock
超时?我使用Oracle 11g,我希望我可以使用类似'select id from table where id = ?1 for update wait 5'
的东西。
我这样定义方法:
@Lock(LockModeType.PESSIMISTIC_WRITE)
Stock findById(String id);
似乎永远锁定,当我在LocalContainerEntityManagerFactoryBean.jpaProperties
中设置javax.persistence.lock.timeout=0
时,没有任何效果。
5条答案
按热度按时间00jrzges1#
要悲观地锁定实体,请将锁定模式设置为
PESSIMISTIC_READ
、PESSIMISTIC_WRITE
或PESSIMISTIC_FORCE_INCREMENT
。如果不能获得悲观锁,但锁定失败没有导致事务回滚,则抛出
LockTimeoutException
。Pessimistic Locking Timeouts
持久性提供者应该等待以获得数据库表上的锁的时间长度(以毫秒为单位)可以使用javax.persistence.lock.timeout属性来指定。如果获得锁所花费的时间超过该属性的值,则将抛出
LockTimeoutException
,但当前事务将不会被标记为回滚。如果该属性设置为0,如果持久性提供程序不能立即获得锁,它应该抛出LockTimeoutException
。如果
javax.persistence.lock.timeout
在多个位置设置,则值将按以下顺序确定:EntityManager
或Query methods
之一的参数。@NamedQuery
注解中的设置。Persistence.createEntityManagerFactory
方法的参数。persistence.xml
部署描述符中的值。Spring Data 1.6以上版本
从Spring Data JPA版本1.6开始,CRUD方法支持
@Lock
(事实上,已经有一个milestone可用)。有关更多详细信息,请参阅ticket。使用该版本,只需声明以下内容:
这将导致后备存储库代理的CRUD实现部分将配置的LockModeType应用于
EntityManager
上的find(…)
调用。另一方面
Spring Data 1.6之前版本
Spring Data pessimistic
@Lock
annotations仅适用于查询(正如您指出的那样)。我不知道有任何注解可以影响整个事务。您可以创建一个findByOnePessimistic
方法,该方法使用pessimistic lock调用findByOne
,或者您可以更改findByOne
以始终获得pessimistic lock。如果你想实现自己的解决方案,你可能可以。在后台,
@Lock
注解由LockModePopulatingMethodIntercceptor
处理,它执行以下操作:你可以创建一些静态锁管理器,它有一个
ThreadLocal<LockMode>
成员变量,然后在每个调用bindResource的存储库中的每个方法周围 Package 一个方面,并在ThreadLocal中设置锁模式。这将允许你在每个线程的基础上设置锁模式。然后你可以创建自己的@MethodLockMode
注解,它将方法 Package 在一个设置线程的方面中。在运行该方法之前,它会锁定特定的锁定模式,并在运行该方法之后将其清除。资源链接:
各种悲观锁超时示例
设置悲观锁
实体对象可以通过lock方法显式锁定:
第一个参数是实体对象,第二个参数是请求的锁模式。
如果调用lock时没有活动事务,则抛出
TransactionRequiredException
,因为显式锁定需要活动事务。如果请求的悲观锁不能被授予,则抛出
LockTimeoutException
:PESSIMISTIC_WRITE
锁,则PESSIMISTIC_READ
锁请求失败。PESSIMISTIC_WRITE
锁或PESSIMISTIC_READ
锁,则PESSIMISTIC_WRITE
锁请求失败。设置查询提示(作用域)
查询提示可以在以下范围内设置(从全局到局部):
对于整个持久性单元-使用
persistence.xml
属性:对于EntityManagerFactory -使用
createEntityManagerFacotory
方法:对于EntityManager -使用
createEntityManager
方法:或者使用setProperty方法:
对于
named query
定义-使用hints
元素:对于特定的查询执行-使用
setHint
方法(在查询执行之前):资源链接:
1.悲观锁定超时
q8l4jmvw2#
您可以在Spring Data中使用
@QueryHints
:57hvy0tb3#
对于Spring Data 1.6或更高版本,我们可以使用spring data jpa提供的@Lock注解。
此外,也可以使用@QueryHints设置锁定超时。最初,在默认的CRUD方法中不支持查询提示注解,但在修复1.6M1后可用。https://jira.spring.io/browse/DATAJPA-173
下面是具有PESSIMISTIC_WRITE模式类型的悲观锁的示例,该模式类型是排他锁。
wgeznvg74#
javax.persistence.lock.timeout似乎对我也不起作用,当提供如下:
但后来我尝试了其他有效的方法,而不是使用@Repository和CrudRepository,现在我正在使用实体管理器配置我的hbernate。使用createQuery沿着lock和设置锁定超时。这个配置按预期工作。我有两个事务在parellel中运行,并试图锁定数据库中的同一行。第一个事务能够获取WRITE锁并在释放锁之前保持锁大约10秒。同时,第二个事务尝试获取同一行上的锁,但由于javax.persistence.lock.timeout设置为15秒,因此,它等待锁被释放,然后获取自己的锁。因此使流序列化。
atmip9wb5#
不幸的是,
javax.persistence.lock.timeout
属性仅由spring data jpa中的oracle提供程序支持。要设置适当的锁定超时,您必须为每个DBMS提供程序执行一些自定义的本地SQL语句。下面是一些特定于DBMS的语句,用于将锁定超时设置为3秒:
MySQL
set session innodb_lock_wait_timeout = 3
PostgreSQL
set local lock_timeout = 3000
SQLServer
set lock_timeout 3000
有关该主题的更多信息,请参阅以下帖子:https://blog.mimacom.com/handling-pessimistic-locking-jpa-oracle-mysql-postgresql-derbi-h2/