【问题标题】:Hibernate many to one foreign key not getting set休眠多对一外键未设置
【发布时间】:2012-02-05 12:15:27
【问题描述】:

我有一个相当简单的一对多关系

[SampleAliasMask] has many [SampleAliasMaskPart]

我的问题是,当我使用集合部件持久化 SampleAliasMask 的新实例时,我得到一个约束违规,即从 SampleAliasMaskPart 到 SampleAliasMask 的表的外键链接被设置为 NULL。

我正在使用休眠注释进行映射:

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

关系的另一半映射如下:

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

ClientEntity的相关部分是

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

我正在创建这样的部分:

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

我得到的确切错误是:

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

我怀疑这个问题与我从未明确设置 SampleAliasMaskPart.sampleAliasMask 的事实有关,但我为什么需要这样做?这种关系从未暴露或导航。该字段仅用于映射目的,这让我认为我映射错了。

【问题讨论】:

  • 添加为评论,因为它没有回答您的问题,但认为您想知道。 @Length 验证字符串长度。你想要@Size。
  • 谢谢,这正是我想要的,是的

标签: java hibernate spring hibernate-mapping hibernate-annotations


【解决方案1】:

你的假设是正确的。 Hibernate 使用关联的拥有方来知道关联是否存在。而拥有方就是没有 mappedBy 属性的一方。

一般规则是,当您具有双向关联时,您有责任通过初始化/修改关联的双方来使对象图保持一致。 Hibernate 不太关心它,但如果你不初始化拥有方,它就不会持久化关联。

请注意,您不必强制将此关联设为双向。如果你不这样做,那么将部分添加到掩码就足够了,因为这一面(这是唯一的一面)是拥有的一面。

【讨论】:

【解决方案2】:

JB Nizet 建议正确。有两种方法可以解决:

  1. 去除双向关系:去除SampleAliasMaskPart中simpleAliasMask的注解@ManyToOne(optional = false, fetch = FetchType.LAZY)

  2. 通过类似component.setSimpleAliasMask(mask) 的操作将mask 添加到每个component。这将建立双向关系。

【讨论】:

    猜你喜欢
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多