持续存在的实体
本节介绍如何使用 Spring Data JPA 持久化(保存)实体。
拯救实体
保存实体可以通过以下方式实现CrudRepository.save(...)方法。它通过使用底层的JPA来持久化或合并给定实体实体管理器.如果该实体尚未被持久化,Spring Data JPA 会通过调用entityManager.persist(...)方法。否则,它调用entityManager.merge(...)方法。
实体状态检测策略
Spring Data JPA提供以下策略来检测实体是否新成立:
-
版本-属性和Id-属性检查(默认): 默认情况下,Spring Data JPA 首先检查是否存在非原语类型的 Version-属性。 如果存在,则该实体被视为新实体,且该性质的价值为
零. 没有这样的版本属性,Spring Data JPA 会检查给定实体的标识符属性。 如果标识符属性为零,则假设该实体是新的。 否则,人们就认为它不是新的。 与其他Spring Data模块不同,JPA考虑了0(零)作为实体的第一个插入版本,因此,原始版本性质不能用来判断某个实体是否新。 -
实施
持久性: 如果一个实体实现持久性,Spring Data JPA 将新的检测委托给isNew(...)实体的方法。 详情请参见Java文档。 -
实施
实体信息: 你可以自定义实体信息抽象形式用于SimpleJpaRepository通过创建 的子类实现JpaRepositoryFactory并且覆盖getEntityInformation(...)相应地进行方法。然后你必须注册 的自定义实现JpaRepositoryFactory作为春豆。请注意,这通常很少是必要的。详情请参见Java文档。
选项1不适用于使用手动分配标识符且无版本属性的实体,因为这些标识符总是非零.
在这种情景下,常见的模式是使用一个通用基类,默认以瞬态标志表示新实例,并在持久化作时使用 JPA 生命周期回调来反转该标志:
@MappedSuperclass
public abstract class AbstractEntity<ID> implements Persistable<ID> {
@Transient
private boolean isNew = true; (1)
@Override
public boolean isNew() {
return isNew; (2)
}
@PostPersist (3)
@PostLoad
void markNotNew() {
this.isNew = false;
}
// More code…
}
| 1 | 宣布旗帜以控制新州。暂时的,这样它就不会被持久化到数据库里。 |
| 2 | 在 的实现中返回旗标Persistable.isNew()这样Spring Data仓库就知道是否需要调用EntityManager.persist()或......合并(). |
| 3 | 声明使用 JPA 实体回调的方法,使得在仓库调用后,标志被切换为表示已有实体保存(...)或者由持久化提供者创建实例。 |