Cmobilecom JPA 2.0.1 Developer Guide

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
ConverterNative QueryFrames / No Frames