【问题标题】:Hibernate best approach for one Java class and multiple tables?一个Java类和多个表的休眠最佳方法?
【发布时间】:2011-01-25 12:51:56
【问题描述】:

换一种说法:如何将重用的子类/表建模/映射到许多不同的父实体?

我有几种实体类型,每种都保存在自己的表中:

A 类 --> 表 A B类->表B ....

现在我需要将这些类中的每一个都设为 1:M 单向子集合的父类。该集合是实体随着时间的推移获得的批准的历史记录。 Child 域类称为“ApprovalItem”。 Approval 类对于所有类型的父母都是完全相同的。

映射它的最佳方法是什么?如果我创建一个表来保存所有 ApprovalItems,那么我无法强制与实体的 PK 建立 FK 关系和/或我留下了糟糕的数据库设计。

另一方面,我可以为每种实体类型(例如 A_ApprovalItems、B_ApprovalItems 等)创建一个 ApprovalIems 表。这在数据库方面似乎是一个很好的模式,但似乎我需要在 Java 中为每个实体批准创建一个单独的域类(例如 AAprrovalItem 类、BApprovalItem 类等)。在 Java 中创建如此多的新类似乎很麻烦和复杂,除了允许我放入不同的 JPA 映射注释之外什么都不做。

Hibernate 中是否有一种映射技术,允许我根据集合的父所有者是谁,将 Java 中的一个类映射到多个不同的表?

【问题讨论】:

    标签: java hibernate mapping


    【解决方案1】:

    我可以为每种实体类型(例如 A_ApprovalItem、B_ApprovalItem 等)创建一个 ApprovalItem 表。这似乎是数据库端的一个很好的架构

    但是

    似乎我需要在 Java 中为每个实体批准创建一个单独的域类(例如 AAprrovalItem 类、BApprovalItem 类等)。

    你不需要它。您可以创建单个 ApprovalItem 类并在父类和 ApprovalItem 之间创建 @OneToMany 关系。 Hibernate 注意为每个关系创建链接表。

    @Entity
    public class ClassA {
    
        @Id
        @GeneratedValue 
        private Integer id;
    
        // Hibernate will create CLASSA_APPROVALITEM to link both class
        @OneToMany
        private List<ApprovalItem> approvalItemList;
    
    }
    
    @Entity
    public class ClassB {
    
        @Id
        @GeneratedValue 
        private Integer id;
    
        // Hibernate will create CLASSB_APPROVALITEM to link both class
        @OneToMany
        private List<ApprovalItem> approvalItemList;
    
    }
    

    还有你的 ApprovalItem 类

    @Entity
    public class ApprovalItem {
    
        @Id
        @GeneratedValue 
        private Integer id;
    
        // Nothing else
    
    }
    

    但是让我们看看 Java Persistence with Hibernate 这本书是怎么说的

    您可能对 Bid 对象有共享引用。如前所述,用户可能有一组对他们所做的投标实例的引用。如果不先删除这些引用,您将无法删除项目及其所有出价。如果您尝试提交此事务,您可能会遇到异常,因为可能违反外键约束

    所以在处理共享引用时请记住这一点。

    为了查看目标架构的样子,您可以使用以下内容

    AnnotationConfiguration configuration = new AnnotationConfiguration();
    
    configuration
        .addAnnotatedClass(ClassA.class)
        .addAnnotatedClass(ClassB.class)
        .addAnnotatedClass(ApprovalItem.class)
        .setProperty(Environment.USER, <TYPE_YOUR_USER>)
        .setProperty(Environment.PASS, <TYPE_YOUR_PASSWORD>)
        .setProperty(Environment.URL, <TYPE_YOUR_URL>)
        .setProperty(Environment.DIALECT, <TYPE_YOUR_DIALECT>)
        .setProperty(Environment.DRIVER, <TYPE_YOUR_DRIVER>);
    
    SchemaExport schema = new SchemaExport(configuration);
    schema.setOutputFile("schema.sql");
    
    schema.create(<DO_YOU_WANT_TO_PRINT_TO_THE_CONSOLE>, <DO_YOU_WANT_TO_EXPORT_THE_SCRIPT_TO_THE_DATABASE>);
    

    它将生成一个名为 schema.sql 的文件,其中包含您的目标架构

    问候,

    【讨论】:

    • 在 Java 方面看起来很完美,但您能详细说明一下数据库中的模式是什么样的吗?我认为实体表和approvalitem 表之间有一个连接表——对吗?
    • @HDave 是的,我们有三个类:ClassA、ClassB 和 ApprovalItem;和五个表:CLASSA、CLASSB、APPROVALITEM、CLASSA_APPROVALITEM(注意链接 ClassA 和 ApprovalItem 实例) CLASSB_APPROVALITEM(注意链接 ClassB 和 ApprovalItem 实例)
    【解决方案2】:

    Chapter 8. Inheritance Mapping 的 Hibernate 文档可能会有所帮助。

    否则,我认为拥有多个“什么都不做”的 ApprovalItem 派生类没有问题,就像你说的那样,因为它确实区分了 Approval,所以就像获得了一种批准。看到您的模型是这样的,我建议您使用多个类,即使它们仅继承自您的基础 ApprovalItem 类。

    我是否很好地理解了您的问题,还是我遗漏了其他更微妙的东西?

    【讨论】:

    • 我认为你完全理解了这个问题。我只是想避免类的多样性,因为我有 12 个这些实体和 3 个不同的子集合。那是 36 个域类,除了持有不同的 JPA 注释之外什么都不做。只是讨厌持久性污染我的域表示的想法!但是,如果没有更好的结果出现,您的建议就是我会做的......谢谢。
    • 我明白你的意思并理解你的论点。尽管如此,它并没有污染你的领域模型,它只是在精确化它。也许是您的模型不足以满足您当前的需求。不管怎样,很高兴我帮了忙。 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多