Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 如何在JPA中明确说明一个实体是新的(暂时的)?_Spring_Hibernate_Jpa_Spring Data Jpa - Fatal编程技术网

Spring 如何在JPA中明确说明一个实体是新的(暂时的)?

Spring 如何在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;

我使用的是Spring Data
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();