Joined Inheritance :
Joined inheritance is a type of inheritance in which the fields from the superclass and the subclass are stored in separate database tables. The subclass tables have a foreign key relationship with the superclass table, and the superclass table contains only the fields that are common to all of the subclasses.
Example of Joined Inheritance
Let’s dive into the details of the Joined Inheritance strategy in Hibernate with an example.
Suppose we have an inheritance hierarchy consisting of the following classes:
Vehicle (parent class) Car (subclass of Vehicle) Bike (subclass of Vehicle)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Vehicle {
private Long id;
private String make;
private String model;
// getters and setters
}
public class Car extends Vehicle {
private Integer numOfDoors;
// getters and setters
}
public class Bike extends Vehicle {
private Boolean isElectric;
// getters and setters
}
Database Table Structure for Joined Inheritance
Let’s start by defining the table structure based on our inheritance classes using Joined Inheritance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CREATE TABLE vehicle (
id BIGINT NOT NULL AUTO_INCREMENT,
make VARCHAR(255),
model VARCHAR(255),
PRIMARY KEY (id)
);
CREATE TABLE car (
id BIGINT NOT NULL,
num_of_doors INTEGER,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES vehicle(id)
);
CREATE TABLE bike (
id BIGINT NOT NULL,
is_electric BOOLEAN,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES vehicle(id)
);
The vehicle table has three columns, id, make, and model. The id column is the primary key for the vehicle table.
The car table has two columns, id and num_of_doors. The id column is a foreign key that references the id column in the vehicle table.
The bike table has two columns, id and is_electric. The id column is a foreign key that references the id column in the vehicle table.
Note that the id column in the car and bike tables is also a primary key in its respective table. This is because each id value should be unique within its table.
Here’s what the entity classes might look like:
Entity Class Hierarchy in JPA/Hibernate
Here’s what the entity classes might look like :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Entity
@Table(name = "vehicle")
@Inheritance(strategy = InheritanceType.JOINED)
public class Vehicle {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String make;
private String model;
// getters and setters
}
@Entity
@Table(name = "car")
public class Car extends Vehicle {
private Integer numOfDoors;
// getters and setters
}
@Entity
@Table(name = "bike")
public class Bike extends Vehicle {
private Boolean isElectric;
// getters and setters
}
In the parent class Vehicle, we have defined the common attributes of all vehicles, such as make and model. We have also added an id field with a @GeneratedValue annotation to ensure that each entity has a unique identifier.
In the subclasses Car and Bike, we have added additional attributes that are specific to each vehicle type. For example, the Car class has an attribute numOfDoors, and the Bike class has an attribute isElectric.
We have also added a @Table annotation to each entity class, which specifies the name of the database table that the entity maps to.
Note that in the parent class Vehicle, we have added a @Inheritance annotation with the value InheritanceType.JOINED. This annotation tells Hibernate to use the “Joined Inheritance” strategy for this entity hierarchy.
Saving Entities
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Vehicle vehicle = new Vehicle();
vehicle.setMake("Toyota");
vehicle.setModel("Camry");
Car car = new Car();
car.setMake("Honda");
car.setModel("Civic");
car.setNumOfDoors(4);
Bike bike = new Bike();
bike.setMake("Yamaha");
bike.setModel("YZF-R6");
bike.setIsElectric(false);
session.save(vehicle);
session.save(car);
session.save(bike);
transaction.commit();
session.close();
In the example above, we first create a Hibernate Session object by calling the openSession() method on a SessionFactory object. We also begin a new transaction using the beginTransaction() method on the Session object.
Next, we create three entities, one Vehicle, one Car, and one Bike. We set the attributes of each entity as appropriate.
Finally, we save each entity to the database using the save() method on the Session object. We then commit the transaction and close the session.
Database Table Data View
The database table data for each table would look like:
vehicle table:
id | make | model |
---|---|---|
1 | Toyota | Camry |
2 | Honda | Civic |
3 | Yamaha | YZF-R6 |
car table:
id | num_of_doors |
---|---|
2 | 4 |
bike table:
id | is_electric |
---|---|
2 | 3 |
Note that the car and bike tables only contain the specific attributes for those entities, and their id column serves as a foreign key reference to the vehicle table. This is because of the joined inheritance strategy, where the child entities only store their specific attributes in their respective tables, and the parent attributes are stored in the parent table.
Also note that in the vehicle table, the id column has been auto-incremented and assigned values of 1, 2, and 3 for the Vehicle, Car, and Bike entities respectively. This is because Hibernate has automatically generated unique identifier values for each entity based on the database configuration.
Retrieving Entities
1
2
3
4
5
6
7
8
9
10
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
List<Vehicle> vehicles = session.createQuery("FROM Vehicle", Vehicle.class).getResultList();
List<Car> cars = session.createQuery("FROM Car", Car.class).getResultList();
List<Bike> bikes = session.createQuery("FROM Bike", Bike.class).getResultList();
transaction.commit();
session.close();
Conclusion
The advantage of using joined inheritance is that it reduces the amount of null values in the table, since each subclass has its own table with only the fields that apply to it. However, it can be less efficient in terms of database performance, since queries often involve multiple tables.