首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Hibernate :多个实体的一对多映射

Hibernate :多个实体的一对多映射
EN

Stack Overflow用户
提问于 2017-08-29 02:12:00
回答 2查看 1.6K关注 0票数 1

假设我们有四个实体A、B、C和Document。

代码语言:javascript
运行
复制
A -> Many Documents (one-to-many)
B -> Many Documents (one-to-many)
C -> Many Documents (one-to-many)

A、B、C可以有多个文档。在传统的一对多映射方式中,我们将有如下文档表:

文档表:

|doc_id | doc_field_1 | doc_field_2 | A_id | B_id | C_id |

如果我添加一个实体的文档,那么对于这些文档,B_id和C_id将为空。B和C的文档也是如此。希望问题是明确的。

我希望文档实体只保留一个id和实体类,这样我就可以用hibernate的方式查询文档表。

或者任何其他解决问题的方法。

EN

回答 2

Stack Overflow用户

发布于 2017-08-29 08:45:18

Thorben Jansssen为此写了一篇很棒的博客文章。

https://www.thoughts-on-java.org/complete-guide-inheritance-strategies-jpa-hibernate/

对于您的情况,单表策略可能是合适的。如果你不希望a_id,b_id,c_id为null,你可以用2列替换它们:

|doc_id | doc_field_1 | doc_field_2 |类型| entity_id|

和实体映射,如下:

代码语言:javascript
运行
复制
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
@Table(name = "document")
public abstract class Document {
    // ...
}


@Entity
@DiscriminatorValue(value = "A")
public class DocumentOfTypeA extends Document{
    ...
    @ManyToOne
    @Column(name="entity_id")
    A aEntity;
}

和你的实体类:

代码语言:javascript
运行
复制
// A.java
public class A{
    // ...
    // @OneToMany (...)
    private Set<DocumentOfTypeA> documents;
}

B和C实体也是如此。

票数 2
EN

Stack Overflow用户

发布于 2019-01-06 05:33:59

请注意,每个对象A、B、C在其表中也有一个ID字段。在大多数情况下,这些都是由数据库使用序列生成器生成的:

代码语言:javascript
运行
复制
@SequenceGenerator(name = "seqA", sequenceName = "seqA_gen")

@Entity
public class A {


  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqA")
  @Id
  private Long Id

  @OneToMany (...)
  private Set<Document> documents;

}

类A的ID值可以与类B或类C相同。如果使用单个表存储所有三个类的文档行,则在正常情况下,必须使用Id以外的其他属性来确定哪些行属于某个对象。如您所示,这可以使用多个ID列完成,也可以使用单个Id列和一个鉴别器列来完成,该列本质上是"this ID is for class A“

所以这里有另一种方法:对于所有三个类,只使用一个Id序列生成器。

这可以通过对所有三个类使用相同的sequenceName来完成。

代码语言:javascript
运行
复制
@SequenceGenerator(name = "seqA", sequenceName = "shared_gen")
@SequenceGenerator(name = "seqB", sequenceName = "shared_gen")
@SequenceGenerator(name = "seqC", sequenceName = "shared_gen")

如果使用相同的序列生成器,则If永远不会重叠,并且可以使用document表中的单个列为所有父类链接@onetomany。从来不存在按Id查询返回不同父级的数据的情况。

第二种可能更常见的方法是使用随机UUID作为类A、B和C的Id生成器。这些Id占用额外的内存,但提供了统计上完全的隔离。

这两种方法使得可以将任意数量的新类添加到包括一组文档的应用程序中,而无需修改Documents表中的列或要求开发人员跟踪鉴别值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45925061

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档