休眠 - 使用包含父 ID 的复合键 - OneToMany
Posted
技术标签:
【中文标题】休眠 - 使用包含父 ID 的复合键 - OneToMany【英文标题】:Hibernate - using composite key that contains a parent id - OneToMany 【发布时间】:2016-12-27 17:34:20 【问题描述】:(原问题已更改,请参阅下面的更新。)
我无法让 hibernate 设置子对象的主键。主键与父主键相同。
这是父母的样子:
@Entity
@Table(name = "PARENT")
@SequenceGenerator(name = "SEQ", allocationSize = 1, sequenceName = "seq_parent_id")
public class Parent
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ")
private Long id;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Fetch(value = FetchMode.SUBSELECT)
@JoinColumn(name = "PARENT_ID")
private Set<Child> children;
这就是孩子的样子:
@Entity
@Table(name = "CHILDREN")
public class Child
@Id
@Column(name = "PARENT_ID")
private Long parentId;
现在,当我运行 JUnit 存储库测试并尝试将父实体与子实体一起保存时,出现异常:
org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): ...
让hibernate自动将 Child.parentId 设置为 parent.id 的正确方法是什么?
我试着给孩子一个父母。但是遇到了其他异常,因为 Parent 不是 Id。
更新
我意识到孩子的 ID 不是真正的主键。它只是一个映射键。 parent.id 可以有多个子条目。
更新
现在我开始意识到我真正需要的是什么:
孩子的主键是三个值的复合键:父 id 和另外两个 String 值。
@Entity
@Table(name = "CHILDREN")
public class Child
@Column(name = "PARENT_ID")
private Long parentId;
@Column(name = "PROPERTY_NAME")
private String propertyName;
@Column(name = "ANOTHER_PROPERTY")
private String anotherProperty;
@Column(name = "PROPERTY_VALUE")
private String propertyValue;
所以我需要使用 parentId、properyName 和 anotherProperty 映射复合键。 propertyValue 是该条目的实际值。
我想我可能需要使用 IdClass 或 embeddedId。我试过了,但到目前为止没有成功。
【问题讨论】:
您应该在关系的另一端声明 JoinColumn。在Child
类中声明@ManyToOne
关系。但是IMO,你有一个设计问题:如果Parent
有多个Child
,Parent
怎么可能是Child
的主键? (多个Child
将具有相同的Parent
,因此具有相同的主键)。
哦,你是对的。这不是真正的主键!!!只是一把钥匙!!该表没有真实 ID。
【参考方案1】:
这可能取决于您的预期语义,但如果子 PK 也是父级的 FK,那么我会假设它表示 IS-A 类型关系 - 或者,用数据库术语来说,该 CHILD 是一个扩展表家长。您可以将其设置为每个类的表继承。
更新
所以根据您的更新,Child 中的 ParentID 不是 Child 的 PK;这意味着它不应使用 @Id
进行注释,而应像任何其他 FK 一样设置。我会考虑不映射 ParentID,而是映射 Parent,虽然 YMMV。
然后一个单独的问题是,孩子的唯一 ID 是什么(如果有的话 - 尽管如果没有的话,您可能会遇到麻烦)是什么?它是独立分配的代理人吗?包含父 ID 的组合?或者是其他东西?所有这些情况都可以适应,但如果没有更多关于您需要哪些信息的信息,我可能无法详细说明每种可能性......
【讨论】:
不确定我是否理解正确,但我不会将其视为 Parent 表的扩展,因为 Parent 可以有很多孩子。 如果一个父节点可以有多个子节点,那么子表上的 PK 不能是父 PK 的 FK。 其实child的唯一键是一个复合键,包含三个值:parent的id和另外两个String值。以上是关于休眠 - 使用包含父 ID 的复合键 - OneToMany的主要内容,如果未能解决你的问题,请参考以下文章