Spring 如何在JPA中明确说明一个实体是新的(暂时的)?
我使用的是Spring DataSpring 如何在JPA中明确说明一个实体是新的(暂时的)?,spring,hibernate,jpa,spring-data-jpa,Spring,Hibernate,Jpa,Spring Data Jpa,我使用的是Spring DataJPA存储库,Hibernate是JPA的提供者 通常,直接使用Hibernate时,由程序员决定EntityManager#persist()和EntityManager#save()。对于Spring数据存储库,只有save()。我不想在这里讨论利弊。让我们考虑下面的简单基类: @MappedSuperclass public abstract class PersistableObject { @Id private String id;
JPA存储库,Hibernate是JPA的提供者
通常,直接使用Hibernate时,由程序员决定EntityManager#persist()
和EntityManager#save()
。对于Spring数据存储库,只有save()
。我不想在这里讨论利弊。让我们考虑下面的简单基类:
@MappedSuperclass
public abstract class PersistableObject {
@Id
private String id;
public PersistableObject(){
this.id = UUID.randomUUID().toString();
}
// hashCode() and equals() are implemented based on equality of 'id'
}
使用这个基类,Spring数据存储库无法判断哪些实体是“新的”(尚未保存到DB),因为在这种情况下,id==null
的定期检查显然不起作用,因为UUID被急切地分配以确保equals()
和hashCode()
的正确性。因此,存储库似乎总是调用EntityManager#merge()
——这对于临时实体来说显然效率低下
问题是:如果可能的话,我如何告诉JPA(或Spring数据)一个实体是新的,这样它就可以使用EntityManager\persist()
而不是\merge()
我考虑了以下几点(使用JPA生命周期回调):
也许您应该添加@Version列:
@Version
private Long version
如果是新实体,它将是空的我想在这里再加一句话。尽管它只适用于Spring数据而不适用于普通JPA,但我认为值得一提的是Spring提供了
接口,该接口有两种方法:
T getId();
boolean isNew();
通过实现此接口(例如,在开始的问题帖子中),Spring Data JpaRepositories将询问实体本身是否是新的,这在某些情况下非常方便。equals()和hashCode()应该基于业务密钥,而不是数据存储密钥。UUID也是错误的主键,性能方面。感谢您的警告。不幸的是,对于这个没有人玩“坏习惯”牌的问题,几乎不可能想出一个通用的解决方案。最后,这是一种折衷:我宁愿自己管理身份,并拥有一个干净的hashCode()和equals(),而不是让Hibernate查询数据库来检索ID序列中的下一个条目。非常感谢,这正是我想要的!你的回答让我找到了这篇优秀的文章:-这篇文章准确地解释了我的情况。
T getId();
boolean isNew();