JPA table with 2 primary key fields
Asked Answered
T

2

11

I have a table which contains only 2 fields. The table has a composite PK formed by these two fields.

When using Netbeans for creating entity beans from database, the entity bean is not created automatically like other tables that have more than 2 fields.

So I guess I need to create the entity bean myself. What is the best practice for creating this entity bean? Does it have to contain COMPOSITE KEY object or not?

Thearchy answered 6/2, 2013 at 12:33 Comment(1)
@Xavi López: they consitute the PK together.Thearchy
A
30

I don't use NetBeans so I can't really say anything about its mapping tools.

For mapping a composite key, there are a couple of options. You can

  • Define a separate @Embeddable object with the PK fields and use it as @EmbeddedId in your @Entity class

    @Embeddable
    public class MyCompositePK { 
        @Column
        private String fieldA;
        @Column
        private String fieldB;
    }
    @Entity 
    public class MyBean { 
        @EmbeddedId
        private MyCompositePK id;
        @Column
        private String fieldC;
    }
    
  • Define a non-mapped POJO with the PK fields and use it as @IdClass in the @Entity.

    @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()
        }
    }
    

    In this example ClassABId is a static inner class just for convenience.

These options are also explained in Pascal Thivent's excellent answer to this question: How to map a composite key with Hibernate?.

This related question discusses differences between these approaches: Which anotation should I use: @IdClass or @EmbeddedId. Notice the fields' declaration gets duplicated with the @IdClass approach.

Anyhow, I don't think there's an alternative to creating two classes. That's why I asked this question : Mapping a class that consists only of a composite PK without @IdClass or @EmbeddedId. It seems there's an hibernate-specific feature for this.

As a side note, if you've got control over the DB structure, you might also consider avoiding composite keys. There are some reasons to do so.

Anacreontic answered 6/2, 2013 at 12:45 Comment(3)
Given that the object contains only the two primary key fields, can it be its own IdClass?Defazio
@TomAnderson That's interesting. I've never tried. It seems that someone did, with no success. The spec doesn't seem to pronounce on this. Might depend on the implementation.Wommera
@TomAnderson: I don't think so, because the ID class has to implement its equals() method based on just the composite key values.Falconet
E
0

Thanks @XaviLópez. Your explanation fixed my code which was declared as its own IdClass mentioned by @Tom Anderson. When I declared as its own IdClass having 2 @Id columns, a JPA query fetching a list of that entity was returning expected "n" items in the result list but each item in that list is null. But that size "n" is expected. After changing to static inner class which is less of refactoring, its able to return right set of result.

According to me: self referencing IdClass wont work because, the self is already an entity and that needs to be in Persistence Context. If I also have a primary key object of the same type, then there will be two "identical" objects in the persistence context. So, it should not be allowed. Hence, we should not use self referencing @IdClass. Create a static inner class as primary key type which is less intrusive.

Entail answered 7/11, 2013 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.