Java 如何处理多个JVM的并发插入?
我们有一个Spring引导应用程序,它有一个从客户机调用并与DB交互的控制器类。根据条件,控制器检查是否存在唯一值的记录,如果不存在,则创建一个新记录(使用自动生成的主键)并保存它 现在并发问题出现在这种情况下:Java 如何处理多个JVM的并发插入?,java,spring-data-jpa,spring-transactions,concurrentmodification,distributed-transactions,Java,Spring Data Jpa,Spring Transactions,Concurrentmodification,Distributed Transactions,我们有一个Spring引导应用程序,它有一个从客户机调用并与DB交互的控制器类。根据条件,控制器检查是否存在唯一值的记录,如果不存在,则创建一个新记录(使用自动生成的主键)并保存它 现在并发问题出现在这种情况下: A类的两个不同对象想要一个值为b1的B类对象,这两个对象在数据库中同时检查,它们得到null,现在它们试图创建一个值为b1的B类的新对象,出现错误 我试过使用简单的双重锁定方法 final static Object lock = new Object(); public Objec
A类
的两个不同对象想要一个值为b1
的B类
对象,这两个对象在数据库中同时检查,它们得到null
,现在它们试图创建一个值为b1
的B类
的新对象,出现错误
我试过使用简单的双重锁定方法
final static Object lock = new Object();
public Object handle(cs cs, Map<String, Object> headers){
LOGGER.info(" persisting message : " + cs.getcsCode());
F f = repo.findByQuery();
if (f==null ) {
synchronized(lock) {
f = repo.findByQuery;
if (f==null ) {
repo.save(cs.getF1());
}
}
}
return csRepo.save(cs);
}
final static Object lock=new Object();
公共对象句柄(cs、映射头){
info(“持久化消息:+cs.getcsCode());
F=repo.findByQuery();
如果(f==null){
已同步(锁定){
f=repo.findByQuery;
如果(f==null){
repo.save(cs.getF1());
}
}
}
返回csRepo.save(cs);
}
但后来意识到我的应用程序运行在两个JVM上,它们使用一个公共数据库。在讨论了一些问题之后,我想到了另一个选择
@传输(隔离=可重复读取)
但我不确定它是否能在我的场景中工作,正如它的解释所说,它在修改行上的数据时很有用,但我正在创建一个新行。由于这是一个罕见的场景,并且涉及多个JVM,因此我无法确定是否测试它。重新设置此可重复读取是不够的。您的事务需要可序列化的隔离级别。它是否足够或需要其他东西来处理两个JVM?我还没有使用可序列化的隔离级别。但是阅读描述我会说,哪一个VM打开这样一个事务并不重要。因此,据我所知,您甚至可以在一个VM中打开两个这样的事务来测试它。是否不可能对对应于
类B
的数据库表设置唯一约束,让重复插入失败,并捕获并处理代码中的ConstraintViolationException
?为什么在查询repo.findByQuery()
中用于查找记录f
的键在数据库架构中没有标记为唯一的?由于检查唯一性,其他插入将失败。