Can a subclass have the same column name as a superclass?

Viewed 163

I have created database tables using the inheritance mapping. I want all tables to have audit columns.

Database schema

Here is the code:

  • An abstract Auditable class
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {

    @CreatedDate
    private LocalDateTime createdAt;
    
    @CreatedBy
    private String createdBy;
}
  • a Person class:
@Entity
@Table(name = "person")
@Inheritance(strategy = InheritanceType.JOINED)
public class Person extends Auditable {

    private String name;
}

  • a Student class:
@Entity
@PrimaryKeyJoinColumn(name = "person_id")
public class Student extends Person {
   private int grade;
}
  • and a Staff class:
@Entity
@PrimaryKeyJoinColumn(name = "person_id")
public class Staff extends Person {
   private int salary;
}

My problem is only the created_at and created_by of the Person table are generated, but the created_at and created_by of Staff and Student tables are null.

Is it possible to have the created_at and created_by of the Staff and Student tables generated too?

1 Answers

The reason you are having trouble is because this is a one-to-one association and not an inheritance.

This mapping is not going to work because when you use inheritance, you are stating that a Student is a Person, and therefore, the moment you create a student is the same moment you create a person. So, there is no reason to have those two columns duplicated among the tables.

But also, you are using InheritanceType.JOINED, basically asking to not share common columns among tables.

The only way this mapping makes sense is if those columns represent different creation times. For example, when a person was born and when it became a student. If that's the case, you can use this mapping:

    @Entity
    @PrimaryKeyJoinColumn(name = "person_id")
    public static class Student extends Person {
        int grade;

        @Column(name = "createdAt")
        LocalDateTime studentCreatedAt;

        @Column(name = "createdBy")
        String studentCreatedBy;
    }

    @Entity
    @PrimaryKeyJoinColumn(name = "person_id")
    public static class Staff extends Person {

        int salary;

        @Column(name = "createdAt")
        LocalDateTime staffCreatedAt;

        @Column(name = "createdBy")
        String staffCreatedBy;
    }

If this is not the case, then Person is not a superclass of Student and Staff and you can represent your database with this mapping:

    @Entity
    public class Person extends Auditable {
        @Id
        Long id;
        String name;
    }

    @Entity
    public class Student extends Auditable {
        @Id
        Long id;

        int grade;

        @MapsId
        @OneToOne
        Person person;
    }

    @Entity
    public class Staff extends Auditable {
        @Id
        Long id;

        int salary;

        @MapsId
        @OneToOne
        Person person;
    }

Where @MapsId tells Hibernate ORM that the column person_id is also the key for that table. Therefore you don't need @PrimaryKeyJoinColumn(name = "person_id").

Related