【问题标题】:Save Hibernate entity with parend child relationships fails with foreign key error保存具有父子关系的 Hibernate 实体因外键错误而失败
【发布时间】:2014-08-27 00:03:37
【问题描述】:

我被侵犯了 - 尝试保存 Hibernate 实体时找不到父键

我有父实体:

@Entity
@Table(name = "parents")
public class Parent implements Serializable {
    private static final long serialVersionUID = 1246376778314918671L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
    @SequenceGenerator(name = "seq", sequenceName = "PARENT_ID_SEQ", allocationSize = 1)
    @Column(name = "parent_id")
    private long parentId;

    @Column(name = "display_name")
    @Size(min = 1, max = 128)
    @NotBlank   
    private String displayName;

    @JsonManagedReference("childAssignments")
    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval=true)
    private Set<ChildAssignment> childAssignments = new HashSet<ChildAssignment>(0);

    //regular getters and setters here
}

子实体看起来像(在数据库中,它在父表的 parent_id 字段上有外键):

Entity
@Table(name = "child_assignments")
public class ChildAssignment implements Serializable {
    private static final long serialVersionUID = -5949955576511639261L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
    @SequenceGenerator(name = "seq", sequenceName = "CHILD_ASSIGNMENT_ID_SEQ", allocationSize = 1)
    @Column(name = "child_assignment_id")
    private long childAssignmentId;

    @Column(name = "parent_id")  
    private long parentId;   // getting error because after creating new parent it has not been set

    @Column(name = "site_id")
    private long siteId;

    @ManyToOne
    @JoinColumn(name = "parent_id", insertable = false, updatable = false)
    private Parent parent;

    // regular getters and setters here

}

在创建父对象和 childAssignments 对象后,我将 childAssignment 添加到父对象

ChildAssignment ca = new ChildAssignment();
ca.setSiteId(1);
// I do not set parent_id here since I do not know it and expecting Hibernate to figure it out

parent.getChildAssignments().add(childAssignment);
session.save(parent);

预期结果是使用 ID 保存新的父条目,并在使用此 id 保存子项后,但似乎休眠在保存时不知道 parent_id,我应该如何建立我的关联以使其工作?还是 parent_id 字段上的一些注释?

更新

我尝试在 childAssignment 实体上删除 parent_id 或将其设置为 @Transient,并得到新错误 cannot insert NULL into table,很明显 Hibernate 正在尝试插入 parent_id 但不填充它,

对孩子设置父母也无济于事

ChildAssignment ca = new ChildAssignment();
   ca.setSiteId(1);
   ca.setParent(parent)

   parent.getChildAssignments().add(childAssignment);
   session.save(parent);

我错过了什么?

已解决

我解决了更改 childAssignment 实体的问题

@Transient -- add transient (just to have it)
@Column(name = parent_id", insertable = false, updatable = false) -- add insertable and updatable  both equals to false
private parentId; 


.....

 @ManyToOne
 @JoinColumn(name = "parent_id") -- remove  insertable = false, updatable = false options
 private Parent parent;

【问题讨论】:

  • 我的子实体类会是什么样子?
  • 我认为我在提供的示例中没有正确的解决方案,我不应该更改任何数据库设置来完成它。

标签: java hibernate


【解决方案1】:

你需要做的:

ca.setParent(parent);

也是。

如果您指定双边关系,那么您必须在 Java 代码中分配双方,就像它是纯 Java 一样。

其次,您对“parentId”列的声明是多余的。 Hibernate 会自动为您创建。

【讨论】:

  • 嗨,这可能很好地解决了这个问题......但如果你能提供一些关于它如何工作以及为什么工作的解释会很好:) 不要忘记 - 有很多新手在 Stack Overflow 上,他们可以从你的专业知识中学到一两件事——对你来说显而易见的事情对他们来说可能并不那么明显。
  • 不,它没有 ca.setNotification(parent); parent.getchildAssignments().add(ca);
  • 问题是child parent_id没有设置,怎么知道怎么设置?
  • 它知道如何设置它,因为你应该调用 ca.setParent(parent)。这样做的能力是 Hibernate/JPA 存在理由的一部分。您几乎不应该关心键值,尤其是将它们分配给属性。
猜你喜欢
  • 1970-01-01
  • 2015-08-01
  • 2016-06-30
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-17
  • 1970-01-01
相关资源
最近更新 更多