Java 使用@MapsId持久化@OneToOne子实体将抛出;错误:分离的实体传递给persist";冬眠
我读书。 我尝试了如下建议配置(使用SpringDataJPA,Hibernate5.0作为供应商): 首先,我尝试了这个例子:Java 使用@MapsId持久化@OneToOne子实体将抛出;错误:分离的实体传递给persist";冬眠,java,spring,hibernate,jpa,spring-data-jpa,Java,Spring,Hibernate,Jpa,Spring Data Jpa,我读书。 我尝试了如下建议配置(使用SpringDataJPA,Hibernate5.0作为供应商): 首先,我尝试了这个例子: PaperSetting paperSettingInDb = paperSettingRepository.findOne(1); PaperSubjectType paperSubjectType = new PaperSubjectType(); paperSubjectType.setSubjectCode("91"); paperSubjectType.se
PaperSetting paperSettingInDb = paperSettingRepository.findOne(1);
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setSubjectCode("91");
paperSubjectType.setPaperSetting(paperSettingInDb);
paperSubjectTypeRepository.save(paperSubjectType);
错误:分离的实体传递给persist:PaperSetting。
似乎hibernate在级联时将纸张设置作为分离状态
2如果要同时创建PaperSubjectType和PaperSetting,是否需要执行以下操作:
PaperSetting paperSetting = new PaperSetting();
paperSetting.setxx;
PaperSetting paperSettingInDbNew = paperSettingRepository.save(paperSetting);
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setPaperSetting(paperSettingInDbNew);
paperSubjectTypeRepository.save(paperSubjectType);
或者我应该在这种情况下使用双向?
谢谢!我使用Hibernate 5.2,它就像一个符咒
假设您拥有这些实体:
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String registrationNumber;
public Person() {}
public Person(String registrationNumber) {
this.registrationNumber = registrationNumber;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRegistrationNumber() {
return registrationNumber;
}
}
@Entity(name = "PersonDetails")
public static class PersonDetails {
@Id
private Long id;
private String nickName;
@OneToOne
@MapsId
private Person person;
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
这个数据访问逻辑:
Person _person = doInJPA( this::entityManagerFactory, entityManager -> {
Person person = new Person( "ABC-123" );
entityManager.persist( person );
return person;
} );
doInJPA( this::entityManagerFactory, entityManager -> {
Person person = entityManager.find( Person.class, _person.getId() );
PersonDetails personDetails = new PersonDetails();
personDetails.setNickName( "John Doe" );
personDetails.setPerson( person );
entityManager.persist( personDetails );
} );
测试在Hibernate ORM中顺利通过
可能是5.0中的一个bug被修复了,所以您最好升级。1)添加级联选项:
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@MapsId
private PaperSetting paperSetting;
2)有了它,您可以在重新创建两个实体时仅保存PaperSubjectType:
PaperSetting paperSetting = new PaperSetting();
paperSetting.setxx;
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setPaperSetting(paperSettingInDbNew);
paperSubjectTypeRepository.save(paperSubjectType);
我认为您可能忘记了将逻辑包装在@Transactional块中
@Transactional
PaperSetting paperSettingInDb = paperSettingRepository.findOne(1);
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setSubjectCode("91");
paperSubjectType.setPaperSetting(paperSettingInDb);
paperSubjectTypeRepository.save(paperSubjectType);
如果没有这一点,
crudepository.findOne()
将打开它自己的短命事务,因此当您返回findOne()时,实体已经分离,因此错误1)您的配置与我的配置相同。2) 字段“id”没有默认值我在测试中添加了@Transactional@Commit,这次“字段“id”没有默认值“@yuxh您的PaperSubjectType在id上没有自动生成批注。。。因此,您要么在保存之前设置它,要么添加自动生成,我发现原因是:我必须在private PaperSetting PaperSetting上添加@JoinColumn(name=“id”);或者在保存PaperSetting时,它会在PaperSubjectType表中创建一个额外的“paper\u setting\u id”列。你知道为什么吗?如果你使用@MapsId
,我就设置hibernate.hbm2ddl.auto=none,然后再试一次。我必须将@JoinColumn(name=“id”)与@MapsId一起使用,否则插入时找不到“paper\u setting\u id”列
@Transactional
PaperSetting paperSettingInDb = paperSettingRepository.findOne(1);
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setSubjectCode("91");
paperSubjectType.setPaperSetting(paperSettingInDb);
paperSubjectTypeRepository.save(paperSubjectType);