跳到主要内容
版本:3.4.3

持久化实体

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…
}
  • 声明一个标志来保存新的状态。使用 transient 修饰,以便它不会被持久化到数据库中。

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

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