您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何使用Spring Data JPA保存具有手动分配的标识符的实体?

如何使用Spring Data JPA保存具有手动分配的标识符的实体?

基本上,您正在从自动分配的标识符切换到手动定义的标识符,这对JPA和Spring Data级别都有很多影响。

在普通的JPA级别,持久性提供程序不必立即执行单个插入,因为它不必获取标识符值。这就是为什么它通常会延迟语句的执行,直到需要刷新为止(这是对的显式调用EntityManager.flush(),即查询执行),因为这要求数据库中的数据是最新的以提供正确的结果或事务提交。

Spring Data JPA存储库会在调用自动使用认事务save(…)。但是,如果您@Transactional在依次注释的方法调用存储库,则直到离开该方法数据库交互才可能发生。

JPA要求EntityManager客户代码区分保留一个全新实体或对现有实体进行更改。Spring Data存储库希望将客户端代码从不必处理这种区别中解放出来,因为业务代码不应因实现细节而过载。这意味着,Spring Data必须以某种方式将新实体与现有实体区分开。参考文档中描述了各种策略。

如果是手动标识符,则认情况下null将不检查标识符属性的值,因为null根据定义,该属性永远不会。一种标准模式是调整实体以实现Persistable并保持一个短暂的is- new-flag,并使用实体回调注释来翻转该标记

@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,并将此描述的摘要添加到了参考文档中。

Java 2022/1/1 18:19:42 有497人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶