我有这样的设想。我有一个web/rest服务,它接收一个带有业务ID的新记录,并使用hibernateentityManager插入它。然而,存在可以同时进行这样的插入的多个过程。Hibernate save
方法将插入或更新(如果存在相同主键的记录)。
因此,如果多个进程正在执行以下等效操作:
流程1:
MySimple r=new MySimple(1,'tagP1')
mySinmpleRepository.save(r);
流程二:
MySimple r=new MySimple(1,'tagP2')
mySinmpleRepository.save(r);
我需要实现的是一种乐观锁定的形式,如果记录已经存在,则更新失败。
不幸的是,到目前为止发生的情况是,记录得到更新,即使我尝试“插入”一个分离的实体,也没有一个保存方法失败
示例实体:
create table MySimple(
SIMPLE_ID INTEGER NOT NULL,
TAG VARCHAR(200),
primary key PK_MYSIMPLE (SIMPLE_ID)
)
实体:
@Entity
public class MySimple {
@Id
@Column(name="SIMPLE_ID", nullable=false, updateable=false)
private simpleId;
@Column(name="TAG", nullable=false, updateable=true)
private tag;
// getters/setters/etc..
}
public interface MySimpleRepository extends JpaRepository<MySimple, Integer>{
}
1条答案
按热度按时间vu8f3i0k1#
spring-data-jpa
就是这样设计的:因为你实体有外部标识符,spring-data-jpa
永远不会把它当作一个新的实体,而不是调用em.persist()
,它调用em.save()
(在最近的版本中是em.merge()
),这反过来又会导致Hibernate决定如何处理实体:插入或更新:选项如下:
1.利用DB锁,即在进入临界区时锁定数据库中的某些内容,并在保存实体之前执行一些检查。在PostgreSQL中,可以使用咨询锁,在其他DB中,您可以创建一个具有单行的表并锁定它。
1.为您的实体定义一个“technical”
@Id
字段,并使用作为@NaturalId
提供的“business identifier”,在这种情况下,唯一约束将有所帮助1.在这种情况下,不要使用
spring-data-jpa
存储库-使用EnitytManager
API。1.利用Composite Repositories并调用
em.persist()
1.提交一个CR到
spring-data-jpa
项目,要求提供persist
方法或其他一些选项,例如boolean isNew
参数1.利用@Version - hibernate(和
spring-data-jpa
)认为具有null
版本的实体是新的。1.以某种方式尝试在您实体中实现
org.springframework.data.domain.Persistable
,以便告诉spring-data-jpa
在特定场景中它应该将实体视为新的,例如: