保存一个带有子对象的对象在Hibernate/JPA中 – @OneToMany

huangapple go评论73阅读模式
英文:

save an object with childs in Hibernate/JPA - @OneToMany

问题

在Hibernate中,我想要保存一个包含子对象的对象。在父对象中,我有一组其他作为子对象的类。父对象与子对象之间有@OneToMany的关系。

父对象:

@Entity
public class TalentIdentitySetting {

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "setting", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<TalentIdentitySettingPower> settingPowers;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "setting", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<TalentIdentitySettingSpeciality> settingSpecialities;
}

子对象:

@Entity
public class TalentIdentitySettingPower {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "IDENTITY_SETTING_ID", nullable = false)
    private TalentIdentitySetting setting;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "POWER_ID", nullable = false)
    private BasePower power;
}

如何在一个事务中同时保存父对象和子对象。这是我的问题:当子对象要被保存时,父对象尚未被保存,会报父键未找到的错误。实际上,Hibernate 应该先保存父对象,然后再保存子对象。

  • 我尝试过使用 PERSIST 级联选项,但仍然无法解决。

请帮忙解决。

英文:

In Hibernate I want to save an object that has a child.In parent Object I have Set of other classes that are child. The parent hase a @OneToMany relationship with the child.

parent :

@Entity
public class TalentIdentitySetting {

 @OneToMany(fetch = FetchType.LAZY, mappedBy = &quot;setting&quot;, cascade = CascadeType.ALL, orphanRemoval = true)
 private Set&lt;TalentIdentitySettingPower&gt; settingPowers;

 @OneToMany(fetch = FetchType.LAZY, mappedBy = &quot;setting&quot;, cascade = CascadeType.ALL, orphanRemoval = true)
 private Set&lt;TalentIdentitySettingSpeciality&gt; settingSpecialities;

}

child :

@Entity
public class TalentIdentitySettingPower {

 @ManyToOne(fetch = FetchType.LAZY)
 @JoinColumn(name = &quot;IDENTITY_SETTING_ID&quot;, nullable = false)
 private TalentIdentitySetting setting;

 @ManyToOne(fetch = FetchType.LAZY)
 @JoinColumn(name = &quot;POWER_ID&quot;, nullable = false)
 private BasePower power;

}

how I can save parent and child together in one transaction.
This is my problem; When the child wants to be saved the parent has not been saved yet and say parent key not found.
In fact, hibernate should save the parent first and then the child.

  • I used PERSIST cascade but it still didn't work.

please help me.

答案1

得分: 0

我相信你的JPA注解是正确的,很可能是因为在保存之前没有设置好TalentIdentitySettingPower.setting属性。

假设你有以下的代码:

		TalentIdentitySetting setting = new TalentIdentitySetting();
		HashSet<TalentIdentitySettingPower> powers = new HashSet<>();
		powers.add(new TalentIdentitySettingPower());
		powers.add(new TalentIdentitySettingPower());
		powers.add(new TalentIdentitySettingPower());
		setting.setSettingPowers(powers);
		repository.save(setting);

这会失败并抱怨空值问题。

如果你在TalentIdentitySettingPower中添加一个构造方法:

    public TalentIdentitySettingPower(TalentIdentitySetting setting) {
        this.setting = setting;
    }

然后这样写:

		TalentIdentitySetting setting = new TalentIdentitySetting();
		HashSet<TalentIdentitySettingPower> powers = new HashSet<>();
		powers.add(new TalentIdentitySettingPower(setting));
		powers.add(new TalentIdentitySettingPower(setting));
		powers.add(new TalentIdentitySettingPower(setting));
		setting.setSettingPowers(powers);
		repository.save(setting);

这将成功地将值保存到数据库中。

根据你的示例,我创建了一个应用程序,链接在这里:https://github.com/hepoiko/stack-63703687

英文:

I believe your JPA Annotation is correct, this is likely that your TalentIdentitySettingPower.setting is not being set before it saved

Let say if you have the following code

		TalentIdentitySetting setting = new TalentIdentitySetting();
		HashSet&lt;TalentIdentitySettingPower&gt; powers = new HashSet&lt;&gt;();
		powers.add(new TalentIdentitySettingPower());
		powers.add(new TalentIdentitySettingPower());
		powers.add(new TalentIdentitySettingPower());
		setting.setSettingPowers(powers);
		repository.save(setting);

This will fail and complain about null-value issue

If you add a constructor method in TalentIdentitySettingPower

    public TalentIdentitySettingPower(TalentIdentitySetting setting) {
        this.setting = setting;
    }

and

		TalentIdentitySetting setting = new TalentIdentitySetting();
		HashSet&lt;TalentIdentitySettingPower&gt; powers = new HashSet&lt;&gt;();
		powers.add(new TalentIdentitySettingPower(setting));
		powers.add(new TalentIdentitySettingPower(setting));
		powers.add(new TalentIdentitySettingPower(setting));
		setting.setSettingPowers(powers);
		repository.save(setting);

This will successfully save the value into database.

Base on your sample, I create an application https://github.com/hepoiko/stack-63703687

huangapple
  • 本文由 发表于 2020年9月2日 18:31:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63703687.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定