在Hibernate中,将具有@MapsId的@OneToOne子实体持久化会引发“错误:传递给持久化的分离实体”

yux*_*uxh 6 java spring hibernate jpa spring-data-jpa

我阅读了https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/。我尝试了像这样的建议配置(使用spring数据JPA,hibernate 5.0作为供应商):

public class PaperSubjectType{
    @Id
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private PaperSetting paperSetting;
..
}

class PaperSetting{
  @Id
  @GeneratedValue
  private Long id;
..
}
Run Code Online (Sandbox Code Playgroud)

首先,我尝试了以下示例:

PaperSetting paperSettingInDb = paperSettingRepository.findOne(1);
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setSubjectCode("91");
paperSubjectType.setPaperSetting(paperSettingInDb);

paperSubjectTypeRepository.save(paperSubjectType);
Run Code Online (Sandbox Code Playgroud)

错误:已将分离的实体传递给persist:PaperSetting。似乎在级联时休眠将PaperSetting视为已分离

2如果我想同时创建PaperSubjectType和PaperSetting,我需要这样做:

PaperSetting paperSetting = new PaperSetting();
paperSetting.setxx;
PaperSetting  paperSettingInDbNew = paperSettingRepository.save(paperSetting);
PaperSubjectType paperSubjectType = new PaperSubjectType();
paperSubjectType.setPaperSetting(paperSettingInDbNew);
paperSubjectTypeRepository.save(paperSubjectType);
Run Code Online (Sandbox Code Playgroud)

还是在这种情况下应该使用双向?谢谢?

Vla*_*cea 1

我尝试了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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个数据访问逻辑:

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 );
} );
Run Code Online (Sandbox Code Playgroud)

测试在 Hibernate ORM 中顺利通过。

也许这是 5.0 中的一个错误,已修复,因此您最好升级。

  • ,我设置 hibernate.hbm2ddl.auto=none 并重试。我必须将 @ JoinColumn(name = "id") 与 @ MapsId 一起使用,否则插入时会抱怨找不到列 'paper_setting_id' (2认同)