Hibernate inheritance with different primary key

single table inheritance hibernate
hibernate discriminator column
hibernate inheritance mapping using annotations
hibernate polymorphic association
hibernate abstract entity
hibernate interface mapping example
mappedsuperclass vs embeddable
hibernate polymorphism annotation example

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.

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

Hibernate Inheritance Mapping, A practical guide to understanding different inheritance mapping entity also has a foreign key constraint to the primary key of its parent entity. Each strategy results in a different database structure. Entity inheritance means that we can use polymorphic queries for retrieving all the sub-class entities when querying for a super-class. Since Hibernate is a JPA implementation, it contains all of the above as well as a few Hibernate-specific features related to inheritance.

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).

The best way to use entity inheritance with JPA and Hibernate, or we can use separate tables for the base class and subclass entities in which case the subclass table Primary Key is also a Foreign Key to  Hibernate Inheritance Mapping Tutorial. There are three stategies for mapping inheriance relation in hibernate, table per class hierarchy, table per concrete class and table per subclass. Let's see the examples of all the strategies.

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.

Hibernate Inheritance Table Per Subclass With Different Foreign , Hibernate Inheritance Table Per Subclass With Different Foreign Key Names of the foreign keys are not equal to the name of the primary key. When you use the inheritance mapping strategy JOINED, all columns mapped by the superclass get mapped to one database table, and the specific attributes of a subclass get mapped to a different table. Hibernate has to join these 2 tables, whenever you use the subclass. The primary key columns of each table are then used as the join columns.

Inheritance, If force is set to true Hibernate will specify the allowed discriminator values The primary key of this table is also a foreign key to the superclass  The limitation of this approach is that if a property is mapped on the superclass, the column name must be the same on all subclass tables. The identity generator strategy is not allowed in union subclass inheritance. The primary key seed has to be shared across all unioned subclasses of a hierarchy.

Configuring Inheritance for a JPA Entity, If the subclass does not have any additional state over its superclass, a separate table is not required. If the subclass table has primary key column, it serves as a  Introduction to Inheritance in Hibernate. Java is an object oriented language. It is possible to implement Inheritance in Java. Inheritance is one of the most visible facets of Object-relational mismatch. Object oriented systems can model both “is a” and “has a” relationship. Relational model supports only “has a” relationship

Mapping class inheritance in Hibernate 5, No inheritance - just copy superclass properties to subclasses; Table per class of animals are stored in different tables we cannot create foreign key By default primary keys in tables corresponding to mapped classes will  I have to map a legacy table model with Hibernate. It contains a many-to-one association that uses a non-primary key column on the to-one side. Is there any way to map that with Hibernate? Solution: Yes, you can reference any column in your association mapping, that contains unique values, e.g., a natural id.

Comments
  • Do you still see any issues provided in the answer below?
  • if you find the answer helpful kindly share the bounty points. If you need any further clarification pls ask.
  • 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 incompabilities
  • 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.
  • 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.
  • 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 IdClass