简体   繁体   English

Spring Data Jpa:从父实体持久化子实体不会更新子身份

[英]Spring Data Jpa: persisting child entities from parent entity does not update child identity

Environment:环境:

  • OS: Ubuntu 20.04 LTS操作系统:Ubuntu 20.04 LTS
  • Java: OpenJDK 17.0.3 Java:OpenJDK 17.0.3
  • Spring Boot: 2.6.7春季启动:2.6.7
  • MySQL: 8.0.29 MySQL:8.0.29

Is it normal for Spring Data Jpa (or Jpa in general) to NOT update child identity attributes when the child is persisted (saved) via the parent entity repository?当子通过父实体存储库持久化(保存)时,Spring Data Jpa(或一般的 Jpa)更新子身份属性是否正常?

Consider this:考虑一下:

@Entity( name = "Company" )
@Table( name = "COMPANY" )
final public class Company
{
  @Id
  @GeneratedValue( strategy = GenerationType.IDENTITY )
  @Column( name = "ID", updatable = false, nullable = false )
  private Long id = null;

  @OneToMany(
    mappedBy = "company",
    cascade = CascadeType.ALL,
    orphanRemoval = true
  )
  private Set< Phone > phoneSet = new LinkedHashSet<>();

  ...getters/setters...
}

@Entity( name = "Phone" )
@Table( name = "PHONE" )
final public class Phone
{
  @Id
  @GeneratedValue( strategy = GenerationType.IDENTITY )
  @Column( name = "ID", updatable = false, nullable = false )
  private Long id = null;

  @ManyToOne
  @JoinColumn( name = "COMPANY_ID" )
  private Company company = null;

  @Column( name = "number" )
  String number = null;

  ...getters/setters...
}


private void someClassFunction()
{
  .....
  Phone phone = new Phone( company, "1115551234" );
  company.getPhoneSet().add( phone );
  this.companyRespository.save( company );  // <<<< NOTE THIS LINE
  System.out.println( "phone.id: " + phone.getId() );
}

When I call someClassFunction() I get:当我调用someClassFunction()我得到:

phone.id: null

The database assigned id is NOT available to me immediately.我无法立即使用分配的数据库ID I did check the database and the record was inserted (persisted/saved) and MySQL did assign an ID.我确实检查了数据库并插入了记录(持久/保存)并且 MySQL 确实分配了一个 ID。 If I reload the parent class (company) in another function, the child is reloaded and has the correct id.如果我在另一个函数中重新加载父类(公司),则重新加载子类并具有正确的 id。

However, if I modify someClassFunction() to this:但是,如果我将someClassFunction()修改为:

private void someClassFunction()
{
  .....
  Phone phone = new Phone( company, "1115551234" );
  company.getPhoneSet().add( phone );
  this.phoneRespository.save( phone );  // <<<< NOTE THIS LINE
  System.out.println( "phone.id: " + phone.getId() );
}

and then call someClassFunction() I get:然后调用someClassFunction()我得到:

phone.id: 47

The database assigned id is available to me immediately.我可以立即使用数据库分配的ID

I don't find the parent/child persist (ie: this.companyRespository.save( company ) ) behavior disclosed in any online documentation or tutorials.我没有发现任何在线文档或教程中披露的父/子持久(即: this.companyRespository.save(company) )行为。 I am led to believe that persisting from the parent should work the same as persisting the child directly ( ie: this.phoneRespository.save( phone ) ).我被引导相信从父母那里坚持应该与直接坚持孩子一样(即: this.phoneRespository.save(phone) )。

Am I doing something wrong?难道我做错了什么? Do I have an incorrect entity definition?我的实体定义不正确吗?

Yes, this is expected - check the contract on your 'save' method.是的,这是意料之中的 - 检查您的“保存”方法的合同。 It returns an instance which may be a copy of the one you passed in, and it is this instance you need to check and use - it will have its identity set when the entityManager is synchronized with the database (on transaction commit, or if the EntityManager is flushed).它返回一个实例,该实例可能是您传入的实例的副本,并且您需要检查和使用该实例 - 当 entityManager 与数据库同步时(在事务提交时,或者如果EntityManager 已刷新)。

ie IE

  Phone phone = new Phone( company, "1115551234" );
  company.getPhoneSet().add( phone );
  phone.setCompany(company);//Don't forget to set this!
  Company mergedCompanyInstance = this.companyRespository.save( company );
  Phone managedPhone = mergedCompanyInstance.getPhoneSet().get(0);//assuming you have only one in the set, otherwise, check by phone number.
  System.out.println( "phone.id: " + phone.getId() );
  System.out.println( "managedPhone.id: " + managedPhone.getId() );

Spring does some internal checks in the save method to determine if it should call JPA EntityManager merge or persist api. Spring 在 save 方法中进行了一些内部检查,以确定它是否应该调用 JPA EntityManager 合并或持久化 api。 If it calls merge, it returns the managed entity instance from the context (which may be a clone of the one you give it) while if it calls persist, it takes your instance and causes it to become managed.如果它调用merge,它会从上下文中返回托管实体实例(可能是你给它的一个克隆),而如果它调用persist,它会获取你的实例并使其成为托管实例。 It is the managed instance that is returned on any findById and query methods.它是在任何 findById 和查询方法上返回的托管实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 @OneToMany 和 @ManyToOne Spring 数据 JPA 子不更新父 - @OneToMany and @ManyToOne Spring Data JPA Child does not update Parent 如何使用 Spring JPA DATA 仅获取特定的子实体及其具有特定值的父实体 - How to fetch only the specific child entity along with its Parent entities with specific value using Spring JPA DATA 如何使用 Lombok 在 Spring/JPA/Hibernate 中获取带有所有子实体和子实体的父实体 - How to get parent entity with all child entities and child entities of children in Spring/JPA/Hibernate with Lombok 通过JPA联接从父实体返回子实体 - Returning child entities from a parent entity with JPA join Spring Data Jpa OneToMany 同时保存子实体和父实体? - Spring Data Jpa OneToMany save child and parent entities at the same time? Spring JPA从新的子实体合并父实体 - Spring JPA merge parent entity from new child entity Spring Data JPA - 删除子实体而不是在更新时设置为 null? - Spring Data JPA - Delete child entities instead of setting to null on update? 如何在spring-jpa中保存基于实体的从父到子表的数据 - How to save data-from-parent-to-child-tables-based-on-entities-in-spring-jpa 使用spring data jpa保存和更新实体父子的最佳方法 - Best way to save and update entity Parent and child using spring data jpa Spring Data JPA通过从父级获取id与父级实体一起插入子级 - Spring Data JPA insert with child along with parent entity by taking id from parent
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM