【问题标题】:JPA table with 2 primary key fields具有 2 个主键字段的 JPA 表
【发布时间】:2013-01-21 15:49:18
【问题描述】:

我有一个只包含 2 个字段的表。该表具有由这两个字段组成的复合 PK。

当使用 Netbeans 从数据库创建实体 bean 时,实体 bean 不会像其他具有 2 个以上字段的表一样自动创建。

所以我想我需要自己创建实体 bean。创建此实体 bean 的最佳实践是什么?它是否必须包含COMPOSITE KEY 对象?

【问题讨论】:

  • @Xavi López:他们共同构成了 PK。

标签: java jpa orm jpa-2.0 composite-key


【解决方案1】:

我不使用 NetBeans,所以我无法真正谈论它的映射工具。

对于映射复合键,有几个选项。你可以

  • 使用 PK 字段定义一个单独的 @Embeddable 对象并将其用作 @EmbeddedId 在您的 @Entity 类中

    @Embeddable
    public class MyCompositePK { 
        @Column
        private String fieldA;
        @Column
        private String fieldB;
    }
    @Entity 
    public class MyBean { 
        @EmbeddedId
        private MyCompositePK id;
        @Column
        private String fieldC;
    }
    
  • 使用 PK 字段定义一个非映射 POJO,并将其用作 @Entity 中的 @IdClass

    @Entity
    @IdClass(value=ClassAB.ClassABId.class)
    public class ClassAB implements Serializable {
        private String idA;
        private String idB;
    
        @Id
        @Column(name="ID_A")
        public String getIdA(){ return idA; }
        public void setIdA(String idA){ this.idA = idA; }
    
        @Id
        @Column(name="ID_B")
        public String getIdB(){ return idB; }
        public void setIdB(String idB){ this.idB = idB; }
    
        static class ClassABId implements Serializable {
            private String idA;
            private String idB;
    
            public String getIdA(){ return idA; }
            public void setIdA(String idA){ this.idA = idA; }
    
            public String getIdB(){ return idB; }
            public void setIdB(String idB){ this.idB = idB; }
    
            // implement equals(), hashcode()
        }
    }
    

    在这个例子中,ClassABId 是一个静态内部类,只是为了方便。

Pascal Thivent 对这个问题的出色回答也解释了这些选项:How to map a composite key with Hibernate?

此相关问题讨论了这些方法之间的差异:Which anotation should I use: @IdClass or @EmbeddedId。请注意,使用 @IdClass 方法会重复字段的声明。

无论如何,我认为除了创建两个类之外别无选择。这就是我问这个问题的原因:Mapping a class that consists only of a composite PK without @IdClass or @EmbeddedId。似乎有一个特定于休眠的功能。

附带说明,如果您可以控制数据库结构,您还可以考虑避免使用复合键。 There are some reasons to do so.

【讨论】:

  • 鉴于对象只包含两个主键字段,是否可以是自己的IdClass
  • @TomAnderson 这很有趣。我从来没有试过。看来someone did,没有成功。规范似乎没有对此发表意见。可能取决于实施。
  • @TomAnderson:我不这么认为,因为 ID 类必须仅基于复合键值来实现其 equals() 方法。
【解决方案2】:

感谢@XaviLópez。您的解释修复了我的代码,该代码被声明为@Tom Anderson 提到的自己的 IdClass。当我声明它自己的具有 2 个 @Id 列的 IdClass 时,获取该实体列表的 JPA 查询在结果列表中返回预期的“n”个项目,但该列表中的每个项目都是空的。但是这个大小“n”是预期的。改成重构较少的静态内部类后,能够返回正确的结果集。

据我说:自我引用 IdClass 不起作用,因为自我已经是一个实体,需要在持久性上下文中。如果我还有一个相同类型的主键对象,那么持久化上下文中就会有两个“相同”的对象。因此,它不应该被允许。因此,我们不应该使用自引用@IdClass。创建一个静态内部类作为侵入性较小的主键类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 2013-01-03
    • 2015-12-13
    相关资源
    最近更新 更多