2013-10-09 64 views
4

我想在JPA中使用悲观锁定,在Hibernate 3上对Postgres数据库。我无法让锁定超时 - 它似乎永远挂起。JPA悲观锁定尝试永不超时

下面是一个例子:

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毫秒)来获得锁,然后应该抛出的异常。代码会变得僵局。

如果我在两个不同的线程中运行该函数,那么当thread1(em1)释放它时,我发现thread2(带有em2)会获得锁。所以锁定正在发生,只是从不超时。

我得到相同的效果与PESSIMISTIC_WRITE,并与任何超时值(2ms的,0毫秒“不等待”)等

我使用Hibernate的3.6.10决赛(最新的Hibernate 3版)和Postgres jdbc驱动程序9.2-1003.jdbc4(最新的驱动程序)。我正在运行Postgres 8.4数据库。

我发现的所有文档都表明这应该起作用。有任何想法吗?

感谢, 阿拉斯泰尔

回答

5

Postgres SELECT for update语法仅提供了不等待如果无法立即获取锁定的选项。见postgres文档。

要防止操作等待其他事务处理为 提交,请使用NOWAIT选项。对于NOWAIT,如果立即无法锁定所选行 ,则该语句会报告 错误,而不是等待。请注意,NOWAIT仅适用于行级锁 - 所需的ROW SHARE表级锁仍采用普通的 方式(请参见第13章)。如果您需要在不等待的情况下获取表级锁,则可以先使用NOWAIT选项LOCK, 。

当Postgres的工作,我已经观察到,对于超时超过0的任何值将导致休眠发出SELECT FOR UPDATE但是当超时为0,将发行SELECT FOR UPDATE NO WAIT

+0

虽然不是我期待的答案,但看起来与我见过的一致 - 谢谢! – Alastair

+1

如果您不在属性文件中将javax.persistence.lock.timeout设置为零,则查询仅在执行“FOR UPDATE”时执行。如果您将其设置为零(如我所说),则执行“FOR UPDATE NOWAIT”。 –

+0

至少在Hibernate 4.3.x和JPA 2.1中,您可以在查询级别指定这些设置。无论是在@NamedQuery(通过hints属性)还是在通过entityManager.createQuery(CriteriaBuilder.createQuery(Entity ...))使用setHint(...)创建的查询中。 – gkephorus

0

将这个在你的persistence.xml:

<property name="javax.persistence.lock.timeout" value="0"/> 

或致电第一锁定之前设置属性。

+0

嗨马尔西奥,感谢,但事实上也没有这个无论是作为一个persistence.xml变量或作为第一个锁的属性。 – Alastair