Mapping multiple subclasses to same Parent ID in JPA Joined Inheritance

I created the tables Person, PersonExtra, PersonBasic, etc. in my database with the superclass Person and subclasses PersonExtra and PersonBasic.

@Entity
@Table(name = "person")
@Inheritance(strategy = InheritanceType.JOINED)
public class Person {
    @Id
    @Column(name = "id", nullable = false, unique = true, length = 20)
    private String id;
    private String name;
    private String lastname;
    // ...
}

@Entity
@PrimaryKeyJoinColumn(name = "extra_id")
public class PersonExtra extends Person {
    private String code;
    private String subject;
    // ...
}

@Entity
@PrimaryKeyJoinColumn(name = "basic_id")
public class PersonBasic extends Person {
    private String range;
}

If I create a Person first and then try to create a PersonExtra with an existing Person’s ID, I get a duplicate ID error because it tries to persist both Person and PersonExtra. It seems like a person can only have one unique type and can only be created through the subclass.

  • I would like a person to be able to be both a PersonExtra and a PersonBasic at the same time.

When I was modeling the database, it seemed better. I had the idea of using something like inheritance in the database, which could be easier to map.

How can I structure my JPA entities so different subclasses (PersonExtra and PersonBasic) can be created with the same id as the superclass (Person)?

  • I was thinking that maybe creating One to One relations like Person with PersonExtra and Person with PersonBasic could work.
    I liked the idea of having inheritance here but, seems is it not possible in this situation?

  • I was considering using the MappedSuperclass annotation, but isn’t that just for an abstract class when the entity isn’t created in the database?

  • Or maybe should I modify the database and create a one-to-many relationship with roles? Part of me thinks that some of the database semantics could be lost, and implementing the logic later could be complicated.

I’m new to this and I could be wrong.

A logical person can only have one object that provides its identity, so clearly inheritance is the wrong tool here as you noticed through the exception.
You can model this through @OneToOne associations as you already figured out, but depending on the amount and size of the columns, it might be better to just store everything in the main table directly. If you want to encapsulate data a bit, you can still use Java classes and model this as @Embeddable. Just keep in mind that using @OneToOne incurs the cost of needing joins when fetching the containing entity, unless you use bytecode enhancement, which allows to defer the secondary table querying a bit.