Using table per class hierarchy
When using this inheritance strategy, the class hierarchy is represented by multiple classes combined into one de-normalized DB table. A discriminator column identifies the type and the subclass.
Example:
package com.sample public class Vehicle { long id; int noOfTyres; private String colour; // Constructors and getters/setters } package com.sample public class Car extends Vehicle { private String licensePlate; long price; int speed; // Constructors and getters/setters }
And here’s the Database view which contains the DISCRIMINATOR field which will contain either “C” or “V” depending if you are inserting a new Car or a new Vehicle.
Here’s the hibernate configuration:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.sample"> <class name="Vehicle" table="VEHICLE" discriminator-value="V"> <id name="id" column="VEHICLE_ID"> <generator class="native" /> </id> <discriminator column="DISCRIMINATOR" type="string" /> <property name="noOfTyres" type="integer" column="NO_OF_TYRES" /> <property name="colour" type="string" /> <subclass name="Car" extends="Vehicle" discriminator-value="C"> <property name="licensePlate" column="LICENSE_PLATE" /> <property name="price" type="long" /> <property name="speed" type="integer" /> </subclass> </class> </hibernate-mapping>
This is the same, using JPA Annotations:
import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; @Entity @Table(name = "VEHICLE") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="discriminator", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue(value="V") public class Vehicle { @Id @GeneratedValue @Column(name = "VEHICLE_ID") private Long id; @Column(name="NO_OF_TYRES") int noOfTyres; @Column private String colour; // Constructors and Getter/Setter methods, }
import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name="VEHICLE") @DiscriminatorValue("C") public class Car extends Vehicle { @Column(name="license_plate") private String licensePlate; @Column long price; @Column int speed; // Constructors and Getter/Setter methods, }
In the following example we will insert at first a Vehicle class (will into the VEHICLE table using the discriminator “V”), then we will insert a Car Object into the VEHICLE table (using the discriminator “C”)
SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); // Will use discriminator V Vehicle v = new Vehicle(1, 4, "red"); session.save(v); // Will use discriminator C Car car = new Car("AB123456", 15000l, 200); session.save(c); session.getTransaction().commit(); session.close();
Advantage
Since this model uses a denormalized table, it offers the best performance even for in the deep hierarchy since it uses a single select to retrieve data.
Disadvantage
Since the subclass state can’t have not-null constraints data integrity is compromised. Also, because all the state is in the same table, changes to members of the hierarchy require column to be altered, added or removed from the table.