JPA表有2个主键字段

时间:2013-02-06 12:33:52

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

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

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

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

2 个答案:

答案 0 :(得分:29)

我不使用NetBeans,因此我无法真正说出其映射工具。

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

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

    @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。看来这有一个特定于hibernate的功能。

作为旁注,如果您可以控制数据库结构,也可以考虑避免使用复合键。 There are some reasons to do so

答案 1 :(得分:0)

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

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