我试图在我的spring boot应用程序中用jpa和db作为MySQL实现悲观锁。我的目标是让一个存储库首先从db获取一行,然后对其设置锁。当此事务运行时,任何人都不能读取同一行。以下是我实现的代码:
@Repository
@Transactional
public class UserRepo {
@PersistenceContext
private EntityManager entityManager;
/**
*
* @param token
* @param data
* @return
*/
public boolean lockUser(String token, int data) {
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.query.timeout", 0);
User usr = entityManager.find(User.class, token, LockModeType.PESSIMISTIC_WRITE, props);
System.out.println("BEFOREE LOCK = " +
Thread.currentThread().getId() + " user="+usr.getPlayerBalance());
entityManager.lock(usr, LockModeType.PESSIMISTIC_WRITE, props);
System.out.println("AFTER LOCK = " + Thread.currentThread().getId());
if (data>2) {
System.out.println("IN IF BEFORE SLEEP Thread = " + Thread.currentThread().getId());
Thread.sleep(90000);
System.out.println("IN IF AFTER SLEEP Thread = " + Thread.currentThread().getId());
} else {
System.out.println("IN ELSE Thread = " + Thread.currentThread().getId());
} return false;
}
}
现在,当我运行它时,当第一个请求come with data>3时,这个提取行,然后锁定行,线程Hibernate90秒。现在,当第二个请求带有data=1时,线程等待锁(em.find-具有超时为0毫秒的悲观锁)。现在,理想情况下,它应该抛出异常,因为我已经将timeout设置为0。但是第二个线程并没有立即抛出exprection,而且线程从db中读取行然后等待。
lockmodetype.pessimistic_write
用于锁定行,这很容易测试。
我对UserRepo进行了一点调整,以:
@Repository
public class UserRepo {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void lockUser(final Long id, final boolean wait) throws InterruptedException {
entityManager.clear(); // be sure there is nothing in the cache, actually the threads don't share first level cache
final Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.query.timeout", 0);
System.out.println("Thread " + Thread.currentThread().getId() + " EXECUTES SELECT FOR UPDATE");
entityManager.find(User.class, id, LockModeType.PESSIMISTIC_WRITE, props);
if (wait) {
System.out.println("Thread " + Thread.currentThread().getId() + " started blocking!");
Thread.sleep(10000);
System.out.println("Thread " + Thread.currentThread().getId() + " finished blocking!");
}
System.out.println("Thread " + Thread.currentThread().getId() + " FINISHED QUERY");
}
}
我为那次回购创建了一个(不漂亮但功能强大的)测试:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@Transactional
@SpringBootTest
public class UserRepoTests {
@Autowired
private UserRepo userRepo;
@Test
public void testSelectForUpdate() throws InterruptedException {
final Runnable requestOne = () -> {
try {
userRepo.lockUser(1L, true); // this one should wait and block the others
} catch (InterruptedException e) {
}
};
final Runnable requestTwo = () -> {
try {
userRepo.lockUser(1L, false);
} catch (InterruptedException e) {
}
};
final Runnable requestThree = () -> {
try {
userRepo.lockUser(1L, false);
} catch (InterruptedException e) {
}
};
final Thread threadOne = new Thread(requestOne);
threadOne.start();
Thread.sleep(1000); // give the first one some time to start
final Thread threadTwo = new Thread(requestTwo);
threadTwo.start();
final Thread threadThree = new Thread(requestThree);
threadThree.start();
Thread.sleep(20000); // wait before destroying context
}
}
Thread 16 EXECUTES SELECT FOR UPDATE
Hibernate: select user0_.id as id1_31_0_, user0_.player_balance as player_b2_31_0_ from "user" user0_ where user0_.id=? for update
Thread 16 started blocking!
Thread 17 EXECUTES SELECT FOR UPDATE
Hibernate: select user0_.id as id1_31_0_, user0_.player_balance as player_b2_31_0_ from "user" user0_ where user0_.id=? for update
Thread 18 EXECUTES SELECT FOR UPDATE
Hibernate: select user0_.id as id1_31_0_, user0_.player_balance as player_b2_31_0_ from "user" user0_ where user0_.id=? for update
Thread 16 finished blocking!
Thread 16 FINISHED QUERY
Thread 17 FINISHED QUERY
Thread 18 FINISHED QUERY
QueryTimeoutException:查询花费的时间比指定的超时时间长(请参见javax.persistence.query.timeout-该属性是一个提示,可能不会被跟随)
或也在同一页上:
timeout查询以毫秒为单位的超时(整数或字符串),这是Hibernate使用的一个提示,但需要底层数据库的支持(TODO是100%为真,还是我们使用了一些其他技巧)。
我想我已经阅读了关于堆栈溢出的所有Selenium超时问题,但是在我的Selenium webdriver 2.25(Python 2.7绑定)中,隐式超时和显式超时都不起作用,而且“no_timeout_here=”行都将永远挂起-- 所有指针将非常感谢! 10月16日更新 我可以知道您的OS/Python版本吗?
我试图在JPA中通过Hibernate3对Postgres数据库使用悲观锁定。我无法使锁超时--它似乎永远挂着。 这里有一个例子: 按照我的理解,em2应该尝试最多5秒(5000ms)来获得锁,然后应该抛出一个异常。相反,代码变成死锁。 谢谢,阿拉斯泰尔
我是新的完全未来。我试图为元素列表(即参数)调用并行方法,然后将结果组合起来创建最终响应。我还试图设置50毫秒的超时,以便如果调用不返回50毫秒,我将返回默认值。 到目前为止,我已经尝试过: 但我一直得到错误说: 有人能告诉我我在这里做错了什么吗?如果我走错了方向,请纠正我。 谢谢
我创建的VPC具有如下的公共和私有子网: < li >公共子网:堡垒服务器、弹性负载平衡器、igw < li >专用子网:ec2实例(应用程序使用http 8080端口运行),nat网关 以下是监听器配置。 < li >负载平衡器协议:http < li >负载平衡器端口:80 < li >实例协议:http < li >实例端口:8080 当我尝试使用命令wget-O-http://elb-xx
问题内容: 我正在尝试在JPA中使用悲观锁定,而不是针对Postgres数据库使用Hibernate 3。我无法超时锁定-它似乎永远挂着。 这是一个例子: 据我了解,em2应该尝试长达五秒钟(5000毫秒)来获取锁,然后应该抛出异常。而是代码陷入僵局。 如果我在两个不同的线程中运行它,那么我会看到线程2(带有em2)在线程1(em1)释放它后立即获得了锁。因此锁定正在发生,只是永不超时。 我用PE
如何配置可见性超时,以便可以再次读取SQS中的消息? 我将Amazon SQS作为消息队列。消息由多个应用程序发送。我现在使用Spring listener读取队列中的消息,如下所示: 类实现了进一步使用了方法。 我还配置了一个调度器,在一段时间后再次读取队列。它使用