slartidan
slartidan

Reputation: 21608

How to avoid empty child tables when using InheritanceType.JOINED?

I have one JPA superclass and dozens of subclasses. Most of those subclasses do not add specific properties.

When using InheritanceType.JOINED JPA assumes a sub-table for each subclass, resulting in a large number of obsolete database tables, making database administration and queries harder.

My superclass currently looks like this:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
public abstract class Employee {
    @Id public int id;
    public String firstName;
    public String lastName;
    public Date birthday;
}

Some subclasses have specific fields:

@Entity
public class ProjectManager extends Employee {
    public String project;
}

Most subclasses, however, are empty like that:

@Entity
public class Director extends Employee {
}

@Entity
public class FacilityManager extends Employee {
}

These database tables make sense:

employee(id, first_name, last_name, birthday)
project_manager(id, project)

How can I avoid these obsolete tables?

director(id)
facility_manager(id)

If I just do not create them, JPA-validation fails:

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    ...
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [director]
    at org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateTable(SchemaValidatorImpl.java:67) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    ...

Upvotes: 3

Views: 1579

Answers (2)

Mike Nakis
Mike Nakis

Reputation: 62130

  1. Having subclasses without any fields is certainly a valid construct, but in my three decades long career I have never come across the need for such a construct, so I would be willing to bet that either your design is not very well thought out, or you simply have not discovered yet the fields that you are going to need later.

  2. Even if we consider empty subclasses as a legitimate construct to have, your additional request for elision of the corresponding tables is not necessarily a reasonable feature to support. The elision of those tables would probably require few extra if statements here and there in the source code of hibernate, but this type of usage is such an exceedingly rare occurrence, that supporting it is most probably not worth it. It is not worth burdening the source code even the slightest bit, and it is not worth writing the necessary tests to support it.

  3. Even if elision of subclass tables on empty subclasses was to be supported by Hibernate, doing so might cause certain functionality to be lost. For example, it may be that without such tables, it would be impossible for hibernate to be able to answer queries such as "find me all the directors" or "find me all the facility managers". Again, in lieu of a subclass table it may still be possible for hibernate to answer queries of this kind by querying the base class table, but that would not be the normal mode of operation, (it would be more expensive,) so it would require coding a special case inside hibernate to support this exceedingly rare request. Again, not a reasonable thing to do.

  4. In the question you mention "If I just do not create them, ..." --are you sure you are using Hibernate correctly? You should not have to create them, you should be able to have hibernate do that for you. Generally, you should not have to manage the database, (and therefore all these empty tables should not be an issue to you,) because the whole point behind using hibernate is so that we do not have to be dealing with the database. When I use hibernate I rarely look at the tables, I often do not even know what tables are there, hibernate allows me the luxury of simply not having to care, for the most part. A look at the state of the database is advisable every once in a while, to make sure there are no surprises, but this is a far cry from managing the database and being burdened by things such as some unnecessary tables being there.

Upvotes: 0

Simon Martinelli
Simon Martinelli

Reputation: 36223

There is a solution but only when using EclipseLink. Hibernate does not support this:

Mixed Inheritance

JPA requires the inheritance strategy to only be defined in the root class. If you want to use a mixture of SINGLE_TABLE and JOINED this can be achieved through using JOINED inheritance in the root class, and specifying the Table on the subclass to be the same as the parent.

Example: Using JOINED with mixed inheritance

@Entity
// This subclass does not define its own table, but shares its parent's ACCOUNT table.
@Table(name="ACCOUNT")
@DiscriminatorValue("3")
public class StandardAccount extends Account {
   ...
}

Source: https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Inheritance#Mixed_Inheritance

Upvotes: 3

Related Questions