Select for update skip locked from JPA level

做~自己de王妃 提交于 2019-12-21 07:16:31

问题


In my application - Oracle with JPA (EclipseLink), I'm using the following expression to lock the subset of the records in some tables:

select * from MY_TABLE where MY_CONDITIONS for update skip locked

I run it throughout native query, but I have to write that query for all required entities.

Is there any way to skip locked records using pure JPA? Can I implement my own locking policy?

I don't mind changing JPA provider but I want to use JPA API.


回答1:


Hibernate provides the UPGRADE_SKIPLOCKED Lock mode.

Using JPA and Hibernate, to produce a "SKIP_LOCKED" as per Hibernate LockMode documentation, you have to combine the PESSIMISTIC_WRITE JPA LockModeType:

entityManager.find(Department.class, 1, LockModeType.PESSIMISTIC_WRITE);

and the Lock timeout setting, like for example in persistence.xml for your persistence unit:

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

(Note that you can configure this LockMode for complex query as well)

SKIP LOCKED is not part of ANSI SQL. Some RDBMS such the following provide this as a specific feature:

  • MySQL
  • Postgresql
  • Oracle

So with pure JPA, it is not possible to specify a "SKIP LOCKED" in queries. Indeed, as documented in LockModeType, JPA 2.1 only supports the following:

  • NONE
  • OPTIMISTIC
  • OPTIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE
  • READ
  • WRITE

However, to enable SKIP LOCKED in your query you can use these alternatives:

  • Use specific JPA implementation feature, such as Hibernate LockMode which allows to specify the SKIP LOCKED via a JPA query, thanks to a combination of PESSIMISTIC_WRITE LockModeType Lock Timeout specific setting as described above
  • Create a native SQL query as you did



回答2:


I know this post is a bit old, but for the record, just as the accepted answer stated, "javax.persistence.lock.timeout" (org.hibernate.cfg.AvailableSettings#JPA_LOCK_TIMEOUT) set to "-2" (org.hibernate.LockOptions#SKIP_LOCKED) with Hibernate results in "SKIP LOCKED". However, this can be done at run-time without having to set any global settings.

Since 2.0 JPA allows to pass hints along like so

entityManager.find(MyType.class, id, LockModeType.PESSIMISTIC_WRITE, new HashMap<String, Object>() {{
        put("javax.persistence.lock.timeout", "-2");
    }});



回答3:


Oracle doesn't provide a read lock, since it doesn't need one; undo logs make it unnecessary. So, SELECT...FOR UPDATE is really just a WRITE lock for Oracle.

Using JPA, you want to set the LockModeType as a PESSIMISTIC_WRITE.



来源:https://stackoverflow.com/questions/41434169/select-for-update-skip-locked-from-jpa-level

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!