[英]Spring Data Jpa: persisting child entities from parent entity does not update child identity
Environment:环境:
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.