12 Inheritance
Managed entities of a class hierarchy are mapped to database using either SINGLE_TABLE,
JOINED or TABLE_PER_CLASS strategy.
Single Table Strategy
With SINGLE_TABLE strategy, all entities of a class hierarchy are mapped to a single table.
For example,
Employee
/ \
FullTimeEmployee PartTimeEmployee
@Entity
@Table(name="Employee")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="empType", discriminatorType=DiscriminatorType.STRING, length=2)
abstract public class Employee {
@Id
private String id;
}
@Entity
@DiscriminatorValue("FT")
public class FullTimeEmployee extends Employee {
@Column(precision=8, scale=2)
private BigDecimal salary;
}
@Entity
@DiscriminatorValue("PT")
public class PartTimeEmployee extends Employee {
@Column(precision=5, scale=2)
private Float hourlyWage;
}
All attributes of entity class hierarchy are mapped to a single table "Employee" as the
following:
Table: Employee
--------------------------------------
id empType salary hourlyWage
Joined Strategy
With JOINED strategy, entities of a class hierarchy are mapped to different tables using
joins. For example,
Project
/ \
LargeProject SmallProject
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="ProjectType", discriminatorType=DiscriminatorType.CHAR)
@DiscriminatorValue("P")
public class Project {
@Id
private long id;
@Column(nullable=false, length=30, unique=true)
private String name;
}
@Entity
@DiscriminatorValue("L")
@PrimaryKeyJoinColumn(name="projectId")
public class LargeProject extends Project {
private byte yearsToComplete;
}
@Entity
@DiscriminatorValue("S")
public class SmallProject extends Project {
private int daysToComplete;
}
Project LargeProject SmallProject
----------------------- --------------------------- -------------------------
id projectType name projectId yearsToComplete id daysToComplete
The column projectId of LargeProject table and the column id of SmallProject table
are primary keys and also foreign keys referencing its superclass entity table(Project).
They are mapped using annotation @PrimaryKeyJoinColumn or corresponding primary-key-join-column
XML element.
Table Per Class Strategy
With TABLE_PER_CLASS strategy, every entity class in a class hierarchy is mapped to its
own table. For example,
Customer
/ \
BusinessCustomer PersonalCustomer
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
abstract public class Customer {
@Id
private long id;
@Column(nullable=false, length=30, unique=true)
private String name;
}
@Entity
public class BusinessCustomer extends Customer {
private Integer budget;
}
@Entity
public class PersonalCustomer extends Customer {
private Integer income;
}
Each entity class in the hierarchy is mapped to a separated table that contains common
columns for inherited attributes from superclasses.
BusinessCustomer PersonalCustomer
------------------- ------------------------
id name budget id name income
TABLE_PER_CLASS mapping strategy does not support polymorphism and downcasting.
Polymorphism
JPA queries are polymorphic. That is, an entity type in query references to the entity
class itself and all its subclasses in its class hierarchy. For example,
select e from Employee e
update Project set budget = budget + 100000
delete from Project where bugdet >= 100000
Entity type expressions can be used to limit entity classes participating in a query.
For example,
select p from Project p where type(p) in (LargeProject, SmallProject)
Downcasting
Downcasting(treat) is used to cast an entity class to one of its subclasses to access its
attributes in path expressions for FROM or WHERE clause. For example,
select e
from Employer emp join treat(emp.employees FullTimeEmployee) e
where emp.id=1 and e.salary >= 100000;
select p from Project p
where treat(p as LargeProject).yearsToComplete > 3 or
treat(p as SmallProject).daysToComplete < 120