Persisting Entities

本节描述了如何使用 Spring Data JPA 持久化(保存)实体。

Saving Entities

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

Entity State-detection Strategies

Spring Data JPA 提供了以下策略,用于检测实体是否为新实体:

  1. 版本属性和 id 属性检查(default):默认情况下,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 生命周期回调在持久性操作中翻转该标记:

Example 1. A base class for entities with manually assigned identifiers
@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…
}
1 声明一个标志来保存新状态。瞬态,以便它不会持久存储到数据库中。
2 Persistable.isNew() 的实现中返回该标志,以便 Spring Data 存储库知道是否调用 EntityManager.persist()….merge()
3 声明一个使用 JPA 实体回调的方法,以便在存储库调用 save(…) 或持久性提供程序实例创建之后,切换标志以指示现有实体。