Hibernate Table per subclass strategy
When using this strategy, the superclass has a table and each subclass has a table that contains only un-inherited properties: the subclass tables have a primary key that is a foreign key of the superclass.
Example:
package com.sample public class Vehicle { // Constructors and Getter/Setter methods, long id; int noOfTyres; private String colour; } package com.sample public class Car extends Vehicle { // Constructors and Getter/Setter methods, private String licensePlate; long price; int speed; }
To use the table per class hierarchy strategy, you need to represent this structure in database, using two tables, referenced by a foreign key of the superclass.
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" > <id name="id" column="VEHICLE_ID"> <generator class="native" /> </id> <property name="noOfTyres" type="integer" column="NO_OF_TYRES" /> <property name="colour" type="string" /> <joined-subclass name="Car" extends="Vehicle" table="CAR" > <key column="vehicle_id" /> <property name="licensePlate" column="LICENSE_PLATE" /> <property name="price" type="long" /> <property name="speed" type="integer" /> </joined-subclass> </class> </hibernate-mapping>
Here the subclass is mapped using the joined-subclass element ( the subclass table is mapped with the optional attribute table).
This is the same, using JPA Annotations:
import javax.persistence.Column; 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.JOINED) 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.Entity; import javax.persistence.Table; @Entity @Table(name="CAR") @PrimaryKeyJoinColumn(name="VEHICLE_ID") public class Car extends Vehicle { @Column(name="license_plate") private String licensePlate; @Column long price; @Column int speed; // Constructors and Getter/Setter methods, }
Notice the @PrimaryKeyJoinColumn annotation which specifies a primary key column that is used as a foreign key to join to another table.
SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); // This will insert data in the VEHICLE table Vehicle v = new Vehicle(1, 4, "red"); session.save(v); // This will insert data in the VEHICLE table and in the CAR table Car car = new Car(1, 4, "red","AB123456", 15000l, 200); session.save(c); session.getTransaction().commit(); session.close();
Advantage
Does not require complex changes to the database schema when a single parent class is modified. You should use this strategy when there is a requirement to use polymorphic associations and polymorphic queries.
Disadvantage
When the class hierarchy is spread across many classes (depth of inheritance), this strategy can have an impact on performance.