Persisting Entities

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

This section describes how to persist (save) entities with Spring Data JPA.

Saving Entities

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

Saving an entity can be performed with the CrudRepository.save(…) method. It persists or merges the given entity by using the underlying JPA EntityManager. If the entity has not yet been persisted, Spring Data JPA saves the entity with a call to the entityManager.persist(…) method. Otherwise, it calls the entityManager.merge(…) method.

Entity State-detection Strategies

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

Spring Data JPA offers the following strategies to detect whether an entity is new or not:

  1. Version-Property and Id-Property inspection (default): By default Spring Data JPA inspects first if there is a Version-property of non-primitive type. If there is, the entity is considered new if the value of that property is null. Without such a Version-property Spring Data JPA inspects the identifier property of the given entity. If the identifier property is null, then the entity is assumed to be new. Otherwise, it is assumed to be not new.

  2. Implementing Persistable: If an entity implements Persistable, Spring Data JPA delegates the new detection to the isNew(…) method of the entity. See the JavaDoc for details.

  3. Implementing EntityInformation: You can customize the EntityInformation abstraction used in the SimpleJpaRepository implementation by creating a subclass of JpaRepositoryFactory and overriding the getEntityInformation(…) method accordingly. You then have to register the custom implementation of JpaRepositoryFactory as a Spring bean. Note that this should be rarely necessary. See the JavaDoc for details.

对于使用手动分配标识符且没有版本特性的实体,选项 1 是不可能的选项,因为使用这些实体时标识符将始终为非 null。在该场景中,一种常见的模式是使用具有瞬态标记的公共基本类,其默认值为新实例,并使用 JPA 生命周期回调在持久性操作中翻转该标记:

Option 1 is not an option for entities that use manually assigned identifiers and no version attribute as with those the identifier will always be non-null. A common pattern in that scenario is to use a common base class with a transient flag defaulting to indicate a new instance and using JPA lifecycle callbacks to flip that flag on persistence operations:

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 Declare a flag to hold the new state. Transient so that it’s not persisted to the database.
2 Return the flag in the implementation of Persistable.isNew() so that Spring Data repositories know whether to call EntityManager.persist() or ….merge().
3 Declare a method using JPA entity callbacks so that the flag is switched to indicate an existing entity after a repository call to save(…) or an instance creation by the persistence provider.