Blog Spring Boot

Representing Inheritance in Databases: A Comprehensive Guide

In object-oriented programming, inheritance allows a child class to inherit properties and methods from a parent class. Translating this concept into database design can be challenging, as databases are inherently relational. There are four common ways to represent inheritance in databases: Mapped SuperClass, Joined Table, Table per Class, and Single Table. In this blog, we’ll explore these approaches, their implementations, and the pros and cons of each using a use case.


Use Case: User System with Inheritance

We need to design a database for the following user types:

  • User: Base class with attributes name, email, and password. This class is abstract (no objects).
  • Mentor: Inherits from User and adds company and avg_rating.
  • Teaching Assistant (TA): Inherits from User and adds no_of_sessions and avg_rating.
  • Instructor: Inherits from User and adds specialization and avg_rating.

Approach 1: Mapped SuperClass

In this approach, there is no table for the parent class (User). Each child class has its own table, which includes both its attributes and the attributes of the parent class.

Schema:

  • Mentor: name, email, password, company, avg_rating
  • TA: name, email, password, no_of_sessions, avg_rating
  • Instructor: name, email, password, specialization, avg_rating

Pros:

  • Simplifies queries for specific child types (e.g., all mentors).
  • No joins required for retrieving data for a single child type.

Cons:

  • Retrieving all User emails requires union queries across all child tables.
  • Adding a new user type requires schema changes and careful query adjustments.

Example Query:

  • Get all emails: SELECT email FROM Mentor UNION SELECT email FROM TA UNION SELECT email FROM Instructor;

Approach 2: Joined Table

Here, the parent class (User) has its own table, storing attributes common to all users. Each child class has its own table with only child-specific attributes. A foreign key links child tables to the parent table.

Schema:

  • User: id, name, email, password
  • Mentor: user_id, company, avg_rating
  • TA: user_id, no_of_sessions, avg_rating
  • Instructor: user_id, specialization, avg_rating

Pros:

  • Querying all users is fast and straightforward.
  • Allows flexibility for users who may belong to multiple child types.

Cons:

  • Requires joins to retrieve complete data for a specific child type.
  • Slightly more complex schema.

Example Query:

  • Get all emails: SELECT email FROM User;
  • Get instructor emails: SELECT email FROM User JOIN Instructor ON User.id = Instructor.user_id;

Approach 3: Table per Class

This approach includes a table for the parent class and separate tables for each child class. The child tables only store child-specific attributes. When querying, the parent table is used to link data.

Schema:

  • User: id, name, email, password
  • Mentor: id, company, avg_rating
  • TA: id, no_of_sessions, avg_rating
  • Instructor: id, specialization, avg_rating

Pros:

  • Similar to Mapped SuperClass but supports parent class objects.
  • Easy to extend to new user types.

Cons:

  • Querying a specific child type requires joining with the parent table.
  • If a user belongs to multiple child types, data duplication may occur.

Example Query:

  • Get instructor emails: SELECT email FROM User JOIN Instructor ON User.id = Instructor.id;

Approach 4: Single Table

In this approach, all data is stored in a single table, including columns for all attributes across all child types. An additional type column indicates the user type.

Schema:

  • User: id, name, email, password, type, company, avg_rating, no_of_sessions, specialization

Pros:

  • Simplest schema.
  • Querying all users or specific types is straightforward.

Cons:

  • Many null values for unused columns.
  • Wastes storage and violates normalization principles.
  • Adding new types requires schema changes.

Example Query:

  • Get instructor emails: SELECT email FROM User WHERE type = 'Instructor';

Comparison Table

ApproachProsCons
Mapped SuperClassSimplifies child-specific queriesComplex union queries for parent attributes
Joined TableFast parent queries; supports multiple child typesRequires joins for child-specific data
Table per ClassSupports parent objects; easy to extendJoins required for child data; potential duplication
Single TableSimple schema; easy queriesWasted storage; many nulls; harder to extend

Conclusion

The best approach depends on your specific requirements:

  • Use Mapped SuperClass when querying child types is frequent and no parent objects exist.
  • Choose Joined Table for flexibility and scalability when querying all users.
  • Opt for Table per Class if you have parent objects and want a normalized design.
  • Select Single Table for simplicity in smaller projects with limited types.

Understanding the trade-offs of each method is crucial to designing an efficient and maintainable database schema.

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over