简体   繁体   English

休眠多对一外键未设置

[英]Hibernate many to one foreign key not getting set

I have a fairly straightforward one-to-many relationship 我的关系很简单

[SampleAliasMask] has many [SampleAliasMaskPart]

My problem is that when I persist a new instance of SampleAliasMask with collection parts I get an constraint violation that the foreign key link from the tables of SampleAliasMaskPart to SampleAliasMask is being set to NULL. 我的问题是 ,当我使用集合部件持久保存SampleAliasMask的新实例时,遇到约束冲突,即从SampleAliasMaskPart表到SampleAliasMask的外键链接被设置为NULL。

I am mapping using hibernate annotations as such: 我正在使用休眠注释进行映射,例如:

@Entity
@Table(name="SAMPLE_ALIAS_MASK")
public class SampleAliasMask extends ClientEntity {
    @OneToMany(mappedBy = "sampleAliasMask", fetch = FetchType.EAGER, cascade = javax.persistence.CascadeType.ALL, orphanRemoval = true)
    @Cascade(CascadeType.ALL)
    @Length(min = 1, message = "The sample alias mask must have components")
    private Set<SampleAliasMaskPart> components;

With the other half of the relationship mapped as so: 关系的另一半映射为:

@Entity
@Table(name="SAMPLE_ALIAS_MASK_PART")
public class SampleAliasMaskPart extends ClientEntity {
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "SAMPLE_ALIAS_MASK_ID", nullable = false)
    private SampleAliasMask sampleAliasMask;

The relevant part of ClientEntity is ClientEntity的相关部分是

@MappedSuperclass
public abstract class ClientEntity {
    @Id
    @Column(name="ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

I am creating the parts like this: 我正在创建这样的部分:

HashSet<SampleAliasMaskPart> components = new HashSet<>();
for(Map<String, Object> c : this.components) {
    SampleAliasMaskPart component = new SampleAliasMaskPart(Integer.parseInt(c.get("value").toString(), 10), c.get("name").toString());
    result.validate(component);
    components.add(component);
}
mask.setComponents(components);

The exact error I get is: 我得到的确切错误是:

java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("ST"."SAMPLE_ALIAS_MASK_PART"."SAMPLE_ALIAS_MASK_ID")

I suspect the issue has to do with the fact that I never explicitly set SampleAliasMaskPart.sampleAliasMask but why do I need to? 我怀疑问题与以下事实有关:我从未明确设置SampleAliasMaskPart.sampleAliasMask,但为什么我需要这样做? That relationship is never exposed nor navigated. 这种关系永远不会被揭露或浏览。 That field is only there for mapping purposes which makes me think that I'm mapping this wrong. 该字段仅用于映射目的,这使我认为我正在映射此错误。

Your assumption is correct. 您的假设是正确的。 Hibernate uses the owning side of an association to know is the association exists or not. Hibernate使用关联的拥有方来知道该关联是否存在。 And the owning side ai the side where there is no mappedBy attribute. 而拥有方是没有mappedBy属性的一方。

The general rule is that when you have a bidirectional association, it's your responsibility to make the object graph coherent by initializing/modifying both sides of the association. 一般规则是,当您具有双向关联时,您有责任通过初始化/修改关联的两侧来使对象图保持一致。 Hibernate doesn't care much about it, but if you don't initialize the owning side, it won't persist the association. Hibernate不太关心它,但是如果您不初始化拥有方,它将不会持久化关联。

Note that you're not forced to make this association bidirectional. 请注意,您不必强制将此关联设为双向。 If you don't, then adding the part to the mask will be sufficient, because this side (which is the unique side) is the owning side. 如果不这样做,则将零件添加到蒙版就足够了,因为这一面(这是唯一面)是拥有面。

JB Nizet suggested correctly. JB Nizet建议正确。 There are two ways you can solve it: 有两种解决方法:

  1. Removing the bi-directional relationship:Remove the annotation @ManyToOne(optional = false, fetch = FetchType.LAZY) from the simpleAliasMask in SampleAliasMaskPart 删除注释:去除所述双向关系@ManyToOne(optional = false, fetch = FetchType.LAZY)simpleAliasMaskSampleAliasMaskPart

  2. Add the mask to each component by doing something like component.setSimpleAliasMask(mask) . 通过执行类似于component.setSimpleAliasMask(mask)mask添加到每个component This will do the bidirectional relationship. 这将建立双向关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM