1 回答
TA贡献1891条经验 获得超3个赞
您基本上是从自动分配的标识符切换到手动定义的标识符,这在 JPA 和 Spring Data 级别上都会产生一些后果。
数据库操作时序
在普通 JPA 级别,持久性提供程序不一定需要立即执行单个插入,因为它不必获取标识符值。这就是为什么它通常会延迟语句的执行,直到它需要刷新,这是在显式调用 、EntityManager.flush()
查询执行时,因为这需要数据库中的数据是最新的以提供正确的结果或事务提交。
Spring Data JPA 存储库在调用save(…)
. 但是,如果您在依次注释为的方法中调用存储库@Transactional
,则在离开该方法之前可能不会发生数据库交互。
EntityManager.persist(…)
对比。….merge(…)
JPA 要求EntityManager
客户端代码区分是持久保留全新实体还是对现有实体应用更改。Spring Data 存储库希望使客户端代码免于处理这种区别,因为业务代码不应因该实现细节而过载。这意味着 Spring Data 必须以某种方式将新实体与现有实体区分开来。
在手动标识符的情况下,默认检查标识符属性的null
值将不起作用,因为该属性永远不会被null
定义。标准模式是调整实体以实现Persistable
并保留瞬态 is-new-标志,并使用实体回调注释来翻转标志。
@MappedSuperclass
public abstract class AbstractEntity<ID extends SalespointIdentifier> implements Persistable<ID> {
private @Transient boolean isNew = true;
@Override
public boolean isNew() {
return isNew;
}
@PrePersist
@PostLoad
void markNotNew() {
this.isNew = false;
}
// More code…
}
isNew被声明为暂时的,以便它不会被持久化。该类型实现Persistable以便存储库save(…)方法的 Spring Data JPA 实现将使用它。上面的代码会导致使用new将标志设置为 的用户代码创建实体true,但任何类型的数据库交互(保存或加载)都会将该实体转换为现有实体,因此,除了所有后续操作外,这将首先save(…)触发。EntityManager.persist(…)….merge(…)
我借此机会创建了DATAJPA-1600并将此描述的摘要添加到参考文档中。
添加回答
举报