JPA Inheritance demands ID in subclass

Viewed 25850

I have a problem with my jpa domain model. I am just trying to play around with simple inheritance for which I use a simple Person base-class and and a Customer subclass. According to the official documentation (both, JPA and EclipseLink) I only need the ID-attribute/column in the base-class. But when I run my tests, I always get an error telling me that Customer has no @Id?

First I thought the problem lies in the visibility of the id-attribute, because it was private first. But even after I changed it to protected (so the subclass has direct access) it isnt working.

Person:

@Entity @Table(name="Persons")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "TYPE")
public class Person {

    @Id
    @GeneratedValue
    protected int id;
    @Column(nullable = false)
    protected String firstName;
    @Column(nullable = false)
    protected String lastName;

Customer:

@Entity @Table(name = "Customers")
@DiscriminatorValue("C")
public class Customer extends Person {

    //no id needed here

I am running out of ideas and resources to look at. It should be a rather simple problem, but I just dont see it.

7 Answers

You might get this type of error when you're not generating the database schema based in your entities. If that is the case:

1st - Your superclass must always have an @Id

2nd - Your subclass must have some column that identifies the extended class (super class @Id)

3rd - Simplest solution for the presented case above would be add a column id to subclass table, with the corresponding foreign key constraint.

Hope this helps someone! Thumbs up!

As i have seen some answers that might help, but not a complete answer, i'll try to provide one.

As the accepted answer states, you have to declare the inheritance in the base class. There are 4 different ways you can do that:

  • @MappedSuperclass

Will map each concrete class to table

  • @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

Similar to @MappedSuperclass but the superclass is also an entity

  • @Inheritance(strategy = InheritanceType.SINGLE_TABLE)

All concrete classes will be mapped by the same table

  • @Inheritance(strategy = InheritanceType.JOINED)

Every class gets its own table. Joined fields will be mapped by the table for the abstract superclass.

You can read more about JPA inheritance strategies here:
https://www.thoughts-on-java.org/complete-guide-inheritance-strategies-jpa-hibernate/


If the class structure is split up over different projects, you might have to declare the superclass in your persistence.xml, as tk.luczak stated in his answer

Related