spring - 如何在 JPA 中明确声明一个实体是新的( transient 的)?

标签 spring hibernate jpa spring-data-jpa

我正在使用 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() - 这对于 transient 实体来说显然是低效的。

问题是:我如何告诉 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

}

最佳答案

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

T getId();
boolean isNew();

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

关于spring - 如何在 JPA 中明确声明一个实体是新的( transient 的)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29177582/

相关文章:

java - 执行计数语句时 JPA 和 Hibernate 库出现问题

java - Spring LDAP : creating connection

spring - 如何将 JpaTemplate 的使用从 Spring 3.2 迁移到 4.1.4?

java - 无法加载类 [org.postgresql.Driver]

java - hql查询外连接

java - 使用 Hibernate 执行数千次插入时 CPU 利用率高

java - FieldSet readString 方法不读取前导空格

java - 在集成测试期间防止 spring-rabbit 中的@RabbitListener 尝试连接到服务器

java - 有没有办法通过 AuditQuery 识别哪些属性已被修改?

java - 使用级联删除实体