Java 在使用Spring数据时,如何确定是否插入了duplicate?
库-Spring数据JPA、Java8、JUnit-4(用于测试) 我有一个实体,让我们称它为信号量。有多台机器试图创建一行相同的Java 在使用Spring数据时,如何确定是否插入了duplicate?,java,spring,oracle,orm,spring-data-jpa,Java,Spring,Oracle,Orm,Spring Data Jpa,库-Spring数据JPA、Java8、JUnit-4(用于测试) 我有一个实体,让我们称它为信号量。有多台机器试图创建一行相同的信号量。我们只希望他们中的一个成功。下面是发生的情况- 信号量行有一个主键,始终为1 机器A使用Spring数据创建信号量并将其保存到DBsave 机器B认为它也在创建信号量,并调用save,但最终更新了它,而客户机代码不知道它。我可以检查是否存在,但这不能保证任何事情,因为两台机器都可以在其中任何一台创建记录之前进行检查 完成加工后,赢得镶件的机器将清理工作台 除了
信号量。我们只希望他们中的一个成功。下面是发生的情况-
信号量
行有一个主键,始终为1
机器A使用Spring数据创建信号量并将其保存到DBsave
机器B认为它也在创建信号量,并调用save,但最终更新了它,而客户机代码不知道它。我可以检查是否存在
,但这不能保证任何事情,因为两台机器都可以在其中任何一台创建记录之前进行检查
完成加工后,赢得镶件的机器将清理工作台
除了直接使用实体管理器查看实体是否为新实体外,我们还有哪些选择?基本上覆盖Spring数据保存方法
@Transactional
public <S extends T> S save(S entity) {
if(this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return this.em.merge(entity);
}
}
我们使用Oracle作为数据库
下面是Spring的SimpleParepository
save方法,供大家参考
@Transactional
public <S extends T> S save(S entity) {
if(this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return this.em.merge(entity);
}
}
@Transactional
公共存储(S实体){
if(this.entityInformation.isNew(entity)){
这个.em.persist(实体);
返回实体;
}否则{
返回此.em.merge(实体);
}
}
您需要的是乐观锁定,您可以通过在@Entity
类中使用@version
注释的版本字段来实现这一点
例如
下面是我们如何解决这个问题的方法
不要在开始时使用Sprint数据的保存
使用长版本
上的@Version
标记,将其归档到版本以进行乐观锁定李>
使用标准弹簧数据findById
查找记录。如果发现一个,我们会去更新它。如果更新失败,我们知道这台机器失去了它的出价,所以它放弃了
如果没有找到记录,请使用JPApersist
首先插入。如果persist失败,我们知道这台机器失去了它的出价,所以它放弃了
整个过程被包装在一个@事务性注释中李>
如果我们在这里,没有例外,我们知道我们有一个赢家。它继续进行并处理李>
谢谢大家的帮助 你有一些唯一性约束吗?啊,所以你依赖于PK。您是否可以添加另一个字段,其唯一目的是唯一性,但不会自动合并?使用Serializable
隔离级别的事务如何<代码>@Transactional(隔离=隔离.SERIALIZABLE)
。用这个注释您的服务层应该会锁定整个表。@Mikewjtyna问题是Spring数据JPAsave
将合并。我在发布我的答案后立即看到@Mikewjtyna的答案,乐观锁定的工作原理与他解释的完全一样。除非您在保存后刷新实体,否则它应该可以正常工作,因为两个并发事务都有相同的版本,只有一个会成功。乐观锁定不能立即工作,因为正如我上面解释的,Spring数据在保存之前会刷新。