Skip to content

Commit cb3853a

Browse files
committed
docs: update table inheritance
1 parent 67bc5e3 commit cb3853a

File tree

4 files changed

+233
-124
lines changed

4 files changed

+233
-124
lines changed

Diff for: table-inheritance/README.md

+182-118
Original file line numberDiff line numberDiff line change
@@ -2,191 +2,255 @@
22
title: "Table Inheritance Pattern in Java: Modeling Hierarchical Data in Relational Databases"
33
shortTitle: Table Inheritance
44
description: "Explore the Table Inheritance pattern in Java with real-world examples, database schema, and tutorials. Learn how to model class hierarchies elegantly in relational databases."
5-
category: Structural
5+
category: Data access
66
language: en
77
tag:
8-
- Decoupling
8+
- Data access
9+
- Database
10+
- Inheritance
11+
- Persistence
12+
- Polymorphism
913
---
1014

15+
## Also known as
16+
17+
* Class Table Inheritance
18+
* Joined Table Inheritance
19+
1120
## Intent of Table Inheritance Pattern
12-
The Table Inheritance pattern models a class hierarchy in a relational database by creating
13-
separate tables for each class in the hierarchy. These tables share a common primary key, which in
14-
subclass tables also serves as a foreign key referencing the primary key of the base class table.
15-
This linkage maintains relationships and effectively represents the inheritance structure. This pattern
16-
enables the organization of complex data models, particularly when subclasses have unique properties
17-
that must be stored in distinct tables.
1821

19-
---
22+
Represent inheritance hierarchies in relational databases by mapping each class in a hierarchy to a database table.
2023

2124
## Detailed Explanation of Table Inheritance Pattern with Real-World Examples
2225

23-
### Real-World Example
24-
Consider a **Vehicle Management System** with a `Vehicle` superclass and subclasses like `Car` and `Truck`.
26+
Real-world example
2527

26-
- The **Vehicle Table** stores attributes common to all vehicles, such as `make`, `model`, and `year`. Its primary key (`id`) uniquely identifies each vehicle.
27-
- The **Car Table** and **Truck Table** store attributes specific to their respective types, such as `numberOfDoors` for cars and `payloadCapacity` for trucks.
28-
- The `id` column in the **Car Table** and **Truck Table** serves as both the primary key for those tables and a foreign key referencing the `id` in the **Vehicle Table**.
28+
> A classic real-world analogy for the Table Inheritance (Joined Table) pattern is managing employee records in an organization:
29+
> Imagine a company's database storing information about employees. All employees have common attributes (name, employee ID, hire date), stored in a general "Employee" table. However, the company also has different types of employees: Full-time Employees (with a salary and benefits) and Contractors (hourly rate, contract duration). Each employee type has distinct data stored in separate specialized tables ("FullTimeEmployee" and "Contractor"), which reference the main "Employee" table.
30+
> This structure mirrors the Table Inheritance pattern—shared fields in a common table and unique fields split into subclass-specific tables.
2931
30-
This setup ensures each subclass entry corresponds to a base class entry, maintaining the inheritance relationship while keeping subclass-specific data in their own tables.
32+
In plain words
3133

32-
### In Plain Words
33-
In table inheritance, each class in the hierarchy is represented by a separate table, which
34-
allows for a clear distinction between shared attributes (stored in the base class table) and
35-
specific attributes (stored in subclass tables).
34+
> The Table Inheritance pattern maps each class within an inheritance hierarchy to its own database table, storing common attributes in a base table and subclass-specific attributes in separate joined tables.
3635
37-
### Martin Fowler Says
36+
Martin Fowler says
3837

39-
Relational databases don't support inheritance, which creates a mismatch when mapping objects.
40-
To fix this, Table Inheritance uses a separate table for each class in the hierarchy while maintaining
41-
relationships through foreign keys, making it easier to link the classes together in the database.
38+
> Relational databases don't support inheritance, which creates a mismatch when mapping objects. To fix this, Table Inheritance uses a separate table for each class in the hierarchy while maintaining relationships through foreign keys, making it easier to link the classes together in the database.
4239
43-
For more detailed information, refer to Martin Fowler's article on [Class Table Inheritance](https://martinfowler.com/eaaCatalog/classTableInheritance.html).
40+
Mind map
4441

42+
![Table Inheritance Pattern Mind Map](./etc/table-inheritance-mind-map.png)
4543

4644
## Programmatic Example of Table Inheritance Pattern in Java
4745

48-
49-
The `Vehicle` class will be the superclass, and we will have `Car` and `Truck` as subclasses that extend
50-
`Vehicle`. The `Vehicle` class will store common attributes, while `Car` and `Truck` will store
51-
attributes specific to those subclasses.
46+
The `Vehicle` class will be the superclass, and we will have subclasses `Car` and `Truck` that extend `Vehicle`. The superclass `Vehicle` stores common attributes, while subclasses store their own specific attributes.
5247

5348
### Key Aspects of the Pattern:
5449

55-
1. **Superclass (`Vehicle`)**:
56-
The `Vehicle` class stores attributes shared by all vehicle types, such as:
57-
- `make`: The manufacturer of the vehicle.
58-
- `model`: The model of the vehicle.
59-
- `year`: The year the vehicle was manufactured.
60-
- `id`: A unique identifier for the vehicle.
50+
**Superclass (`Vehicle`):**
51+
52+
The superclass stores shared attributes:
53+
54+
* `make`: Manufacturer of the vehicle.
55+
* `model`: Model of the vehicle.
56+
* `year`: Year of manufacture.
57+
* `id`: Unique identifier for the vehicle.
6158

62-
These attributes are stored in the **`Vehicle` table** in the database.
59+
These common attributes will reside in a dedicated database table (`Vehicle` table).
6360

64-
2. **Subclass (`Car` and `Truck`)**:
65-
Each subclass (`Car` and `Truck`) stores attributes specific to that vehicle type:
66-
- `Car`: Has an additional attribute `numberOfDoors` representing the number of doors the car has.
67-
- `Truck`: Has an additional attribute `payloadCapacity` representing the payload capacity of the truck.
61+
**Subclasses (`Car` and `Truck`):**
6862

69-
These subclass-specific attributes are stored in the **`Car` and `Truck` tables**.
63+
Each subclass adds attributes specific to its type:
7064

71-
3. **Foreign Key Relationship**:
72-
Each subclass (`Car` and `Truck`) contains the `id` field which acts as a **foreign key** that
73-
references the primary key (`id`) of the superclass (`Vehicle`). This foreign key ensures the
74-
relationship between the common attributes in the `Vehicle` table and the specific attributes in the
75-
subclass tables (`Car` and `Truck`).
65+
* `Car`: `numberOfDoors`, indicating how many doors the car has.
66+
* `Truck`: `payloadCapacity`, representing how much payload the truck can carry.
7667

68+
Each subclass stores these specific attributes in their respective tables (`Car` and `Truck` tables).
69+
70+
**Foreign Key Relationship:**
71+
72+
Each subclass table references the superclass table via a foreign key. The subclass's `id` links to the primary key of the superclass, thus connecting common and subclass-specific data.
73+
74+
### Java Implementation Using JPA Annotations:
7775

7876
```java
79-
/**
80-
* Superclass
81-
* Represents a generic vehicle with basic attributes like make, model, year, and ID.
82-
*/
77+
@Setter
78+
@Getter
8379
public class Vehicle {
84-
private String make;
85-
private String model;
86-
private int year;
87-
private int id;
8880

89-
// Constructor, getters, and setters...
81+
private String make;
82+
private String model;
83+
private int year;
84+
private int id;
85+
86+
public Vehicle(int year, String make, String model, int id) {
87+
this.make = make;
88+
this.model = model;
89+
this.year = year;
90+
this.id = id;
91+
}
92+
93+
@Override
94+
public String toString() {
95+
return "Vehicle{"
96+
+ "id="
97+
+ id
98+
+ ", make='"
99+
+ make
100+
+ '\''
101+
+ ", model='"
102+
+ model
103+
+ '\''
104+
+ ", year="
105+
+ year
106+
+ '}';
107+
}
90108
}
91109

92-
/**
93-
* Represents a car, which is a subclass of Vehicle.
94-
*/
110+
@Getter
95111
public class Car extends Vehicle {
96-
private int numberOfDoors;
97-
98-
// Constructor, getters, and setters...
112+
private int numDoors;
113+
114+
public Car(int year, String make, String model, int numDoors, int id) {
115+
super(year, make, model, id);
116+
if (numDoors <= 0) {
117+
throw new IllegalArgumentException("Number of doors must be positive.");
118+
}
119+
this.numDoors = numDoors;
120+
}
121+
122+
public void setNumDoors(int doors) {
123+
if (doors <= 0) {
124+
throw new IllegalArgumentException("Number of doors must be positive.");
125+
}
126+
this.numDoors = doors;
127+
}
128+
129+
@Override
130+
public String toString() {
131+
return "Car{"
132+
+ "id="
133+
+ getId()
134+
+ ", make='"
135+
+ getMake()
136+
+ '\''
137+
+ ", model='"
138+
+ getModel()
139+
+ '\''
140+
+ ", year="
141+
+ getYear()
142+
+ ", numberOfDoors="
143+
+ getNumDoors()
144+
+ '}';
145+
}
99146
}
100147

101-
/**
102-
* Represents a truck, which is a subclass of Vehicle.
103-
*/
148+
@Getter
104149
public class Truck extends Vehicle {
105-
private int payloadCapacity;
106-
107-
// Constructor, getters, and setters...
150+
private double loadCapacity;
151+
152+
public Truck(int year, String make, String model, double loadCapacity, int id) {
153+
super(year, make, model, id);
154+
if (loadCapacity <= 0) {
155+
throw new IllegalArgumentException("Load capacity must be positive.");
156+
}
157+
this.loadCapacity = loadCapacity;
158+
}
159+
160+
public void setLoadCapacity(double capacity) {
161+
if (capacity <= 0) {
162+
throw new IllegalArgumentException("Load capacity must be positive.");
163+
}
164+
this.loadCapacity = capacity;
165+
}
166+
167+
@Override
168+
public String toString() {
169+
return "Truck{"
170+
+ "id="
171+
+ getId()
172+
+ ", make='"
173+
+ getMake()
174+
+ '\''
175+
+ ", model='"
176+
+ getModel()
177+
+ '\''
178+
+ ", year="
179+
+ getYear()
180+
+ ", payloadCapacity="
181+
+ getLoadCapacity()
182+
+ '}';
183+
}
108184
}
109185
```
110186

187+
### Explanation of the JPA annotations used above:
111188

189+
* `@Entity`: Indicates that the class is a JPA entity mapped to a database table.
190+
* `@Inheritance(strategy = InheritanceType.JOINED)`: Configures joined table inheritance, meaning each class (superclass and subclasses) maps to its own table.
191+
* `@Table(name = "XYZ")`: Explicitly specifies the database table name for clarity.
192+
* `@Id`: Marks the primary key of the entity.
193+
* `@GeneratedValue(strategy = GenerationType.IDENTITY)`: Specifies auto-generation of primary key values by the database.
112194

113-
## Table Inheritance Pattern Class Diagram
195+
### Database Structure Result:
114196

197+
Applying this code will result in three database tables structured as follows:
115198

116-
<img src="etc/class-diagram.png" width="400" height="500" />
199+
**Vehicle table**
200+
* id
201+
* make
202+
* model
203+
* year
117204

205+
**Car table**
206+
* id (FK to Vehicle)
207+
* numberOfDoors
118208

209+
**Truck table**
210+
* id (FK to Vehicle)
211+
* payloadCapacity
119212

120-
121-
122-
123-
## Table Inheritance Pattern Database Schema
124-
125-
### Vehicle Table
126-
| Column | Description |
127-
|--------|-------------------------------------|
128-
| id | Primary key |
129-
| make | The make of the vehicle |
130-
| model | The model of the vehicle |
131-
| year | The manufacturing year of the vehicle |
132-
133-
### Car Table
134-
| Column | Description |
135-
|------------------|-------------------------------------|
136-
| id | Foreign key referencing `Vehicle(id)` |
137-
| numberOfDoors | Number of doors in the car |
138-
139-
### Truck Table
140-
| Column | Description |
141-
|-------------------|-------------------------------------|
142-
| id | Foreign key referencing `Vehicle(id)` |
143-
| payloadCapacity | Payload capacity of the truck |
144-
145-
---
213+
This approach clearly represents the Table Inheritance (Joined Table) pattern, with common attributes centrally managed in the superclass table and subclass-specific attributes cleanly separated in their own tables.
146214

147215
## When to Use the Table Inheritance Pattern in Java
148216

149-
- When your application requires a clear mapping of an object-oriented class hierarchy to relational tables.
150-
- When subclasses have unique attributes that do not fit into a single base table.
151-
- When scalability and normalization of data are important considerations.
152-
- When you need to separate concerns and organize data in a way that each subclass has its own
153-
table but maintains relationships with the superclass.
217+
* When persisting an inheritance hierarchy of Java classes in a relational database.
218+
* Suitable when classes share common attributes but also have distinct fields.
219+
* Beneficial when polymorphic queries across subclasses are frequent.
154220

155221
## Table Inheritance Pattern Java Tutorials
156222

157223
- [Software Patterns Lexicon: Class Table Inheritance](https://softwarepatternslexicon.com/patterns-sql/4/4/2/)
158224
- [Martin Fowler: Class Table Inheritance](http://thierryroussel.free.fr/java/books/martinfowler/www.martinfowler.com/isa/classTableInheritance.html)
159225

160-
---
161-
162226
## Real-World Applications of Table Inheritance Pattern in Java
163227

164-
- **Vehicle Management System**: Used to store different types of vehicles like Car and Truck in separate tables but maintain a relationship through a common superclass `Vehicle`.
165-
- **E-Commerce Platforms**: Where different product types, such as Clothing, Electronics, and Furniture, are stored in separate tables with shared attributes in a superclass `Product`.
228+
* Hibernate ORM (`@Inheritance(strategy = InheritanceType.JOINED)` in Java)
229+
* EclipseLink (Joined Inheritance strategy in JPA)
230+
* Spring Data JPA applications modeling complex domain hierarchies.
166231

167232
## Benefits and Trade-offs of Table Inheritance Pattern
168233

169-
### Benefits
234+
Benefits:
170235

171-
- **Clear Structure**: Each class has its own table, making the data model easier to maintain and understand.
172-
- **Scalability**: Each subclass can be extended independently without affecting the other tables, making the system more scalable.
173-
- **Data Normalization**: Helps avoid data redundancy and keeps the schema normalized.
236+
* Normalized database schema reduces redundancy.
237+
* Clearly models class hierarchies at the database level.
238+
* Easier to implement polymorphic queries due to clear class distinctions.
174239

175-
### Trade-offs
240+
Trade-offs:
176241

177-
- **Multiple Joins**: Retrieving data that spans multiple subclasses may require joining multiple tables, which could lead to performance issues.
178-
- **Increased Complexity**: Managing relationships between tables and maintaining integrity can become more complex.
179-
- **Potential for Sparse Tables**: Subclasses with fewer attributes may end up with tables that have many null fields.
242+
* Increased complexity in database queries involving multiple joins.
243+
* Reduced performance for deep inheritance hierarchies due to costly joins.
244+
* Maintenance overhead increases with the complexity of inheritance structures.
180245

181246
## Related Java Design Patterns
182247

183-
- **Single Table Inheritance** – A strategy where a single table is used to store all classes in an
184-
inheritance hierarchy. It stores all attributes of the class and its subclasses in one table.
185-
- **Singleton Pattern** – Used when a class needs to have only one instance.
186-
248+
* [Single Table Inheritance](https://java-design-patterns.com/patterns/single-table-inheritance/): Alternative strategy mapping an entire class hierarchy into a single database table, useful when fewer joins are preferred at the cost of nullable columns.
249+
* Concrete Table Inheritance – Each subclass has its own standalone table; related in providing an alternate approach to storing inheritance hierarchies.
187250

188251
## References and Credits
189252

190-
- **Martin Fowler** - [*Patterns of Enterprise Application Architecture*](https://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
191-
- **Java Persistence with Hibernate** - [Link to book](https://www.amazon.com/Java-Persistence-Hibernate-Christian-Bauer/dp/193239469X)
192-
- **Object-Relational Mapping on Wikipedia** - [Link to article](https://en.wikipedia.org/wiki/Object-relational_mapping)
253+
* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)
254+
* [Object-Relational Mapping (Wikipedia)](https://en.wikipedia.org/wiki/Object-relational_mapping)
255+
* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)
256+
* [Pro JPA 2: Mastering the Java Persistence API](https://amzn.to/4b7UoMC)

Diff for: table-inheritance/etc/table-inheritance-mind-map.png

222 KB
Loading

0 commit comments

Comments
 (0)