当我尝试在多线程环境中创建数据时遇到问题。在调用super.create()之前,我检查数据库中是否还没有数据。但我相信线程同时调用方法create(),其中一个失败抛出重复键异常而不是IllegalArgumentException:
@Transactional(readOnly=false)
@Override
public T create(T resource){
//check if data already exists
if(this.repository.findById(resource.getId()) != null){
throw new IllegalArgumentException("Resource already exists");
}
//else call create
return super.create(resource);
}
是否有任何意义使其有效?该项目使用spring-data-jpa和Hibernate 4.3.1.Final和Oracle数据库
PS:我需要一个更聪明的解决方案,而不仅仅是捕获异常,因为我在更新过程中遇到了同样的问题,如果资源日期比资源日期更新,我必须检查集成日期是否更新资源。数据库中。我的项目必须在多个节点上运行。
谢谢
答案 0 :(得分:0)
您可以使用带有同步的双重检查锁定(http://en.wikipedia.org/wiki/Double-checked_locking)来强化您的方法,以确保只有一个创建的对象,而其他线程只是跳过创建。诀窍是检查对象是否存在,然后输入一个synchronized块然后再次检查。
伪代码:
if (noObjectExists()) {
synchronized {
if (noObjectExists()) {
// Create object
}
}
}
答案 1 :(得分:0)
如果您确定单resource
只有一个resource.id
,则可以锁定resource
个对象。
@Transactional(readOnly=false)
@Override
public T create(T resource){
synchronized (resource) {
//check if data already exists
if(this.repository.findById(resource.getId()) != null){
throw new IllegalArgumentException("Resource already exists");
}
//else call create
return super.create(resource);
}
}
答案 2 :(得分:0)
<强>插入强>
<强>更新用强>