【问题标题】:How to explictly state that an Entity is new (transient) in JPA?如何在 JPA 中明确声明一个实体是新的(瞬态的)?
【发布时间】:2015-03-20 23:52:05
【问题描述】:

我正在使用 Spring Data JpaRepository,并将 Hibernate 作为 JPA 提供程序。

通常在直接使用 Hibernate 时,EntityManager#persist()EntityManager#save() 之间的决定取决于程序员。使用 Spring Data 存储库,只有 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 Data 存储库无法判断哪些实体是“新的”(尚未保存到 DB),因为在这种情况下,对 id == null 的常规检查显然不起作用,因为 UUID 是热切分配以确保equals()hashCode()的正确性。所以存储库似乎做的是总是调用EntityManager#merge()——这对于瞬态实体来说显然是低效的。

问题是:我如何告诉 JPA(或 Spring Data)一个实体是新的,如果可能的话它使用EntityManager#persist() 而不是#merge()

我正在考虑这些方面的事情(使用 JPA 生命周期回调):

@MappedSuperclass
public abstract class PersistableObject {

     @Transient
     private boolean isNew = true; // by default, treat entity as new

     @PostLoad
     private void loaded(){
         // a loaded entity is never new
         this.isNew = false;
     }

     @PostPersist
     private void saved(){
         // a saved entity is not new anymore
         this.isNew = false;
     }

     // how do I get JPA (or Spring Data) to use this method?
     public boolean isNew(){
         return this.isNew;
     }

     // all other properties, constructor, hashCode() and equals same as above

}

【问题讨论】:

  • equals() 和 hashCode() 应该基于业务密钥而不是数据存储密钥。在性能方面,UUID 也是不好的主键。
  • 感谢您的警告。不幸的是,几乎不可能为这个问题想出一个通用的解决方案,没有人玩“坏习惯!”卡片。最后,这是一个权衡:我宁愿自己管理身份并拥有一个干净的 hashCode() 和 equals(),而不是让 Hibernate 查询数据库只是为了检索 ID 序列中的下一个条目。

标签: spring hibernate jpa spring-data-jpa


【解决方案1】:

我想在这里再补充一句。尽管它仅适用于 Spring Data 而不适用于一般 JPA,但我认为值得一提的是 Spring 提供了 Persistable<T> 接口,它有两种方法:

T getId();
boolean isNew();

通过实现这个接口(例如,在开头的问题帖子中),Spring Data JpaRepositories 将询问实体本身是否是新的,这在某些情况下非常方便。

【讨论】:

    【解决方案2】:

    也许你应该添加@Version 列:

    @Version
    private Long version
    

    如果是新实体,它将为空

    【讨论】:

    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2019-12-19
    相关资源
    最近更新 更多