spring 在Hibernate中,持久化带有@MapsId的@OneToOne子实体会抛出“error:detached entity passed to persistent”(错误:传递给持久化的分离实体)

xv8emn3q  于 2023-11-16  发布在  Spring
关注(0)|答案(4)|浏览(142)

我读了https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/。我尝试了如下建议配置(使用spring data 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;
..
}

字符串
首先,我尝试了这个例子:

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

paperSubjectTypeRepository.save(paperSubjectType);


错误:分离的实体传递到持久化: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);


在这种情况下,我应该使用双向?谢谢!

qvtsj1bj

qvtsj1bj1#

我想您可能忘记了将逻辑 Package 在@ transmitting块中

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

paperSubjectTypeRepository.save(paperSubjectType);

字符串
如果没有这个,crudRepository.findOne()将打开它自己的短暂事务,所以当你得到findOne()的返回时,实体已经被分离了,因此出现错误

pkln4tw6

pkln4tw62#

tried it的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被修复了,所以你最好升级。

xqkwcwgp

xqkwcwgp3#

**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);

7z5jn7bk

7z5jn7bk4#

原因是因为实体处于分离状态。这是如何发生的?您传递的实体不处于持久化状态-这意味着它与持久化上下文无关。因此解决方案之一是:

PaperSetting paperSetting = new PaperSetting();
paperSetting.setxx;
PaperSubjectType paperSubjectType = new PaperSubjectType();

// we create PaperSetting entity and we pass it before saving it,
// as it will bedetached from the persistent context as soon as we save it
paperSubjectType.setPaperSetting(paperSetting);

paperSubjectTypeRepository.save(paperSubjectType);

字符串

相关问题