jjzjj

java - 如何在spring data jpa查询中指定@lock超时?

coder 2023-05-11 原文

如何指定@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 时,没有任何效果。

最佳答案

To lock entities pessimistically, set the lock mode to PESSIMISTIC_READ, PESSIMISTIC_WRITE, or PESSIMISTIC_FORCE_INCREMENT.

If a pessimistic lock cannot be obtained, but the locking failure doesn’t result in a transaction rollback, a LockTimeoutException is thrown.

Pessimistic Locking Timeouts

The length of time in milliseconds the persistence provider should wait to obtain a lock on the database tables may be specified using the javax.persistence.lock.timeout property. If the time it takes to obtain a lock exceeds the value of this property, a LockTimeoutException will be thrown, but the current transaction will not be marked for rollback. If this property is set to 0, the persistence provider should throw a LockTimeoutException if it cannot immediately obtain a lock.

If javax.persistence.lock.timeout is set in multiple places, the value will be determined in the following order:

  1. The argument to one of the EntityManager or Query methods.
  2. The setting in the @NamedQuery annotation.
  3. The argument to the Persistence.createEntityManagerFactory method.
  4. The value in the persistence.xml deployment descriptor.

对于 Spring Data 1.6 或更高版本

@Lock从 Spring Data JPA 1.6 版开始,CRUD 方法支持(事实上,已经有 milestone 可用)。看到这个ticket了解更多详情。

使用该版本,您只需声明以下内容:

interface WidgetRepository extends Repository<Widget, Long> {

  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Widget findOne(Long id);
}

这将导致后备存储库代理的 CRUD 实现部分将配置的 LockModeType 应用到 find(…)调用EntityManager .

另一方面,

对于之前版本的 Spring Data 1.6

Spring Data 悲观@Lock注释仅适用于(如您所指出的)查询。我知道没有注释会影响整个事务。您可以创建 findByOnePessimistic调用 findByOne 的方法用悲观锁或者你可以改变findByOne总是获得一个悲观锁。

如果您想实现自己的解决方案,您可能可以。在引擎盖下 @Lock注释由 LockModePopulatingMethodIntercceptor 处理它执行以下操作:

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);

您可以创建一些具有 ThreadLocal<LockMode> 的静态锁管理器。成员变量,然后在每个存储库中的每个方法周围都有一个方面,这些方法调用 bindResource 并在 ThreadLocal 中设置锁定模式。这将允许您在每个线程的基础上设置锁定模式。然后您可以创建自己的@MethodLockMode将方法包装在一个方面的注释,该方面在运行方法之前设置特定于线程的锁定模式,并在运行方法后清除它。

资源链接:

  1. How to enable LockModeType.PESSIMISTIC_WRITE when looking up entities with Spring Data JPA?
  2. How to add custom method to Spring Data JPA
  3. Spring Data Pessimistic Lock timeout with Postgres
  4. JPA Query API

悲观锁超时的各种例子

设置悲观锁

一个实体对象可以通过lock方法显式锁定:

em.lock(employee, LockModeType.PESSIMISTIC_WRITE);

第一个参数是一个实体对象。第二个参数是请求的锁定模式。

一个 TransactionRequiredException如果在调用 lock 时没有 Activity 事务,则抛出此错误,因为显式锁定需要 Activity 事务。

一个 LockTimeoutException如果请求的悲观锁不能被授予,则抛出:

  • 一个 PESSIMISTIC_READ如果另一个用户(即 由另一个 EntityManager 实例表示)当前持有一个 PESSIMISTIC_WRITE锁定该数据库对象。
  • 一个 PESSIMISTIC_WRITE如果当前有其他用户,则锁定请求失败 持有 PESSIMISTIC_WRITE锁或 PESSIMISTIC_READ锁上 该数据库对象。

设置查询提示(范围)

可以在以下范围(从全局到本地)设置查询提示:

对于整个持久性单元 - 使用 persistence.xml属性:

<properties>
   <property name="javax.persistence.query.timeout" value="3000"/>
</properties>

对于 EntityManagerFactory - 使用 createEntityManagerFacotory方法:

Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
  Persistence.createEntityManagerFactory("pu", properties);

对于 EntityManager - 使用 createEntityManager方法:

Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);

或使用 setProperty 方法:

em.setProperty("javax.persistence.query.timeout", 6000);

对于 named query定义 - 使用 hints元素:

@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
    hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})

对于特定的查询执行 - 使用 setHint方法(查询执行前):

query.setHint("javax.persistence.query.timeout", 8000);

资源链接:

  1. Locking in JPA
  2. Pessimistic Lock Timeout

关于java - 如何在spring data jpa查询中指定@lock超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29765934/

有关java - 如何在spring data jpa查询中指定@lock超时?的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  6. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  7. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  8. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  9. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  10. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

随机推荐