我想在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数据库。
我发现的所有文档都表明这应该起作用。有任何想法吗?
感谢, 阿拉斯泰尔
虽然不是我期待的答案,但看起来与我见过的一致 - 谢谢! – Alastair
如果您不在属性文件中将javax.persistence.lock.timeout设置为零,则查询仅在执行“FOR UPDATE”时执行。如果您将其设置为零(如我所说),则执行“FOR UPDATE NOWAIT”。 –
至少在Hibernate 4.3.x和JPA 2.1中,您可以在查询级别指定这些设置。无论是在@NamedQuery(通过hints属性)还是在通过entityManager.createQuery(CriteriaBuilder.createQuery(Entity ...))使用setHint(...)创建的查询中。 – gkephorus