Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用@MapsId持久化@OneToOne子实体将抛出;错误:分离的实体传递给persist";冬眠_Java_Spring_Hibernate_Jpa_Spring Data Jpa - Fatal编程技术网

Java 使用@MapsId持久化@OneToOne子实体将抛出;错误:分离的实体传递给persist";冬眠

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

我读书。 我尝试了如下建议配置(使用SpringDataJPA,Hibernate5.0作为供应商):

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

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