我正在尝试在JPA中使用悲观锁定,而不是针对Postgres数据库使用Hibernate 3。我无法超时锁定-它似乎永远挂着。
这是一个例子:
EntityManagerFactory factory; // (initialise the factory ) EntityManager em1 = factory.createEntityManager(); EntityManager em2 = factory.createEntityManager(); // em1 gets a lock EntityTransaction transaction1 = em1.getTransaction(); transaction1.begin(); MyObject object1 = em1.find( MyObject.class, 1, LockModeType.PESSIMISTIC_READ ); // em2 tries for a lock Map<String,Object> timeoutProperties = new HashMap<String,Object>(); timeoutProperties.put("javax.persistence.lock.timeout", 5000); EntityTransaction transaction2 = em2.getTransaction(); transaction2.begin(); MyObject object2 = em2.find( MyObject.class, 1, LockModeType.PESSIMISTIC_READ, timeoutProperties ); // After five seconds I expect em2 to bail out, but it never does. transaction1.rollback(); transaction2.rollback();
据我了解,em2应该尝试长达五秒钟(5000毫秒)来获取锁,然后应该抛出异常。而是代码陷入僵局。
如果我在两个不同的线程中运行它,那么我会看到线程2(带有em2)在线程1(em1)释放它后立即获得了锁。因此锁定正在发生,只是永不超时。
我用PESSIMISTIC_WRITE以及任何超时值(2ms,0ms’NO WAIT’)等都会得到相同的效果。
我正在使用Hibernate 3.6.10 Final(最新的Hibernate 3版本)和Postgres jdbc驱动程序9.2-1003.jdbc4(最新驱动程序)。我正在针对Postgres 8.4数据库运行。
我发现的所有文档都建议这样做。有任何想法吗?
谢谢,Alastair
Postgres SELECT for update语法仅提供在无法立即获得锁定的情况下不等待的选项。参见postgres文档。
为防止该操作等待其他事务提交,请使用NOWAIT选项。使用NOWAIT,如果无法立即锁定选定的行,该语句将报告错误,而不是等待。注意,NOWAIT仅适用于行级锁- 所需的ROW SHARE表级锁仍以常规方式获取(请参见第13章)。如果需要不等待就获取表级锁,则可以先将LOCK与NOWAIT选项一起使用。
当我使用postgres时,我已经观察到超时超过0的任何值都会导致hibernate状态,SELECT FOR UPDATE但是当超时为0时就会发出hibernate状态SELECT FOR UPDATE NO WAIT
SELECT FOR UPDATE
SELECT FOR UPDATE NO WAIT