Hibernate inheritance with different primary key
Asked Answered
K

3

6

I'm trying to create a inheritance with TABLE_PER_CLASS strategy, but i want to have different primary key for each table is it possible?

I've one class Register which has millions of instances, some of these instances are "special" and have different rules for theirs columns and extra columns.

@MappedSuperclass

public abstract class Register {


    @Id
    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;


    private Date checked;

    @Column(nullable = false)
    private RegisterState tipo;
}


@Entity
@AttributeOverrides({ @AttributeOverride(name = "userId", column = @Column(nullable = false, unique = false, updatable = false)) })
public class PotencialRegister extends Register implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;


    @Column(length = 64, nullable = false, unique = false)
    private String referer;
}

For the basic register I dont need an Id attribute because I've one unique column, but for the specialized entity that column is not unique so I added an extra attribute.

the problem is that hibernate is using the parent id to created a composite primary key (the generated schema is):

create table PotencialRegister (
        id integer not null,
        userId bigint not null,
        checked datetime(6),
        tipo integer not null,
        referer varchar(64) not null,
        primary key (id, userId)
    )  

    create table Register (
        userId bigint not null,
        checked datetime(6),
        tipo integer not null,
        primary key (userId)
    )  

The columns are right and the schama is what i want, but I would like to remove the "id" member from PotencialRegister primary key.

Kermanshah answered 7/11, 2017 at 2:5 Comment(1)
Do you still see any issues provided in the answer below?Frankie
F
7

You can create another class that do not have @Id column in it and use this class as base class for each type of Register.

so your Register class would look like:

@MappedSuperclass

public abstract class Register {

    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;

    private Date checked;

   @Column(nullable = false)
    private RegisterState tipo;
}

Now for your Normal Register you can do following:

 @Entity   
 public class NormalRegister extends Register implements Serializable{

    @Id
    public Long getUserId(){
      return super.userId;
    }

     public void setUserId(Long uId){
        super.userId=uId;
      }

   }

next you define your PotencialRegister class as:

@Entity
@AttributeOverrides({ @AttributeOverride(name = "userId", column = @Column(nullable = false, unique = false, updatable = false)) })
public class PotencialRegister extends Register implements Serializable {

    private Integer id;


    @Column(length = 64, nullable = false, unique = false)
    private String referer;

    @Id
    public Long getUserId(){
      return super.userId;
    }

     public void setUserId(Long uId){
        super.userId=uId;
      }

}

With this you do not have Id in base class and all the sub classes can define their own Id attribute

Frankie answered 16/11, 2017 at 10:43 Comment(6)
if you find the answer helpful kindly share the bounty points. If you need any further clarification pls ask.Frankie
Actually it doens't solve my problem because i didn't want to have the "id" column... the perfect primary key is the userId if I put it in the abstract class i've the problem i got, if i take off, and put in each exteded class i get incompabilitiesKermanshah
I understand your problem is with PotenicalRegister class where with your implementation id and userId cols become part of primary key as this is inherited from abstract class. With my solution you can have the primary key defined as you want there is no primary key in the abstract class and each implementation of the register class can have its pwn primay key.Frankie
Kindly let me know what incompatibilities you get when you add @Id attribute in each extended class so that we can provide you a solution.Frankie
I got an exception when removing @Id from the base class. I couldn't figure out what's I'm missing. Can you help? Error creating bean with name 'registerRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [....Register] does not define an IdClassAcrospire
I guess you did not added @Id on extended class, in this case Hibernate will not be able to identify the Id column for the entityFrankie
R
1

In table per class hierarchy both Version and Id properties are assumed to be inherited from the root class. If I am not wrong then you cannot use multiple Id attributes in single class/class hierarchy. In your case in the base class you can put the properties which are common across tables and use Id attribute only in the specific classes (representing the individual tables).

Rey answered 20/11, 2017 at 12:21 Comment(0)
I
0

you can't redefine userId as a primary key: https://hibernate.atlassian.net/browse/HHH-11771. So i believe you should consider moving userId from abstract class to implementations with appropriate annotations.

Incredible answered 25/10, 2019 at 7:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.