跳到主要内容

持久化实体

DeepSeek V3 中英对照 Persisting Entities

本节介绍如何使用 Spring Data JPA 持久化(保存)实体。

保存实体

保存实体可以通过 CrudRepository.save(…) 方法执行。它使用底层的 JPA EntityManager 来持久化或合并给定的实体。如果实体尚未被持久化,Spring Data JPA 会通过调用 entityManager.persist(…) 方法来保存该实体。否则,它会调用 entityManager.merge(…) 方法。

实体状态检测策略

Spring Data JPA 提供了以下策略来检测一个实体是否是新的:

  1. 版本属性和标识符属性检查(默认):默认情况下,Spring Data JPA 首先检查是否存在非原始类型的版本属性。如果存在,当该属性的值为 null 时,实体被视为新的。如果没有这样的版本属性,Spring Data JPA 会检查给定实体的标识符属性。如果标识符属性为 null,则假定实体是新的。否则,假定实体不是新的。

  2. 实现 Persistable:如果实体实现了 Persistable,Spring Data JPA 将新实体检测委托给实体的 isNew(…) 方法。详情请参阅 JavaDoc

  3. 实现 EntityInformation:您可以通过创建 JpaRepositoryFactory 的子类并相应地重写 getEntityInformation(…) 方法来自定义 SimpleJpaRepository 实现中使用的 EntityInformation 抽象。然后,您需要将 JpaRepositoryFactory 的自定义实现注册为 Spring bean。请注意,这种情况很少需要。详情请参阅 JavaDoc

对于使用手动分配标识符且没有版本属性的实体来说,选项 1 并不是一个可行的选择,因为在这种情况下,标识符始终是非 null 的。在这种场景中,常见的模式是使用一个带有瞬态标记的通用基类,该标记默认表示一个新实例,并在持久化操作中使用 JPA 生命周期回调来翻转该标记:

示例 1. 一个用于具有手动分配标识符的实体的基类

@MappedSuperclass
public abstract class AbstractEntity<ID> implements Persistable<ID> {

@Transient
private boolean isNew = true; 1

@Override
public boolean isNew() {
return isNew; 2
}

@PrePersist 3
@PostLoad
void markNotNew() {
this.isNew = false;
}

// More code…
}
java
  • 声明一个标志来保存新的状态。使用 transient 修饰,以便它不会被持久化到数据库中。

  • Persistable.isNew() 的实现中返回该标志,以便 Spring Data 仓库知道是调用 EntityManager.persist() 还是 ….merge()

  • 使用 JPA 实体回调声明一个方法,以便在仓库调用 save(…) 或持久化提供者创建实例后,该标志被切换为指示现有实体。