+ + getVehicle(vehicleId : int) : Vehicle
+ + saveVehicle(vehicle : Vehicle) : Vehicle
+ + updateVehicle(vehicle : Vehicle) : Vehicle
+ }
+}
+package com.iluwatar.entity {
+ class Car {
+ - engineCapacity : int
+ + Car()
+ + Car(manufacturer : String, model : String, noOfPassengers : int, engineCapacity : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getEngineCapacity() : int
+ + hashCode() : int
+ + setEngineCapacity(engineCapacity : int)
+ + toString() : String
+ }
+ class Freighter {
+ - flightLength : double
+ + Freighter()
+ + Freighter(manufacturer : String, model : String, countOfSeats : int, loadCapacity : int, flightLength : double)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getFlightLength() : double
+ + hashCode() : int
+ + setFlightLength(flightLength : double)
+ + toString() : String
+ }
+ abstract class PassengerVehicle {
+ - noOfPassengers : int
+ + PassengerVehicle()
+ + PassengerVehicle(manufacturer : String, model : String, noOfPassengers : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getNoOfPassengers() : int
+ + hashCode() : int
+ + setNoOfPassengers(noOfPassengers : int)
+ + toString() : String
+ }
+ class Train {
+ - noOfCarriages : int
+ + Train()
+ + Train(manufacturer : String, model : String, noOfPassengers : int, noOfCarriages : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getNoOfCarriages() : int
+ + hashCode() : int
+ + setNoOfCarriages(noOfCarriages : int)
+ + toString() : String
+ }
+ abstract class TransportVehicle {
+ - loadCapacity : int
+ + TransportVehicle()
+ + TransportVehicle(manufacturer : String, model : String, loadCapacity : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getLoadCapacity() : int
+ + hashCode() : int
+ + setLoadCapacity(loadCapacity : int)
+ + toString() : String
+ }
+ class Truck {
+ + towingCapacity : int
+ + Truck()
+ + Truck(manufacturer : String, model : String, loadCapacity : int, towingCapacity : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getTowingCapacity() : int
+ + hashCode() : int
+ + setTowingCapacity(towingCapacity : int)
+ + toString() : String
+ }
+ abstract class Vehicle {
+ - manufacturer : String
+ - model : String
+ - vehicleId : int
+ + Vehicle()
+ + Vehicle(manufacturer : String, model : String)
+ + Vehicle(vehicleId : int, manufacturer : String, model : String)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getManufacturer() : String
+ + getModel() : String
+ + getVehicleId() : int
+ + hashCode() : int
+ + setManufacturer(manufacturer : String)
+ + setModel(model : String)
+ + setVehicleId(vehicleId : int)
+ + toString() : String
+ }
+}
+package com.iluwatar.abstractEntity {
+ abstract class PassengerVehicle {
+ - noOfPassengers : int
+ + PassengerVehicle()
+ + PassengerVehicle(manufacturer : String, model : String, noOfPassengers : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getNoOfPassengers() : int
+ + hashCode() : int
+ + setNoOfPassengers(noOfPassengers : int)
+ + toString() : String
+ }
+ abstract class TransportVehicle {
+ - loadCapacity : int
+ + TransportVehicle()
+ + TransportVehicle(manufacturer : String, model : String, loadCapacity : int)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getLoadCapacity() : int
+ + hashCode() : int
+ + setLoadCapacity(loadCapacity : int)
+ + toString() : String
+ }
+ abstract class Vehicle {
+ - manufacturer : String
+ - model : String
+ - vehicleId : int
+ + Vehicle()
+ + Vehicle(manufacturer : String, model : String)
+ + Vehicle(vehicleId : int, manufacturer : String, model : String)
+ # canEqual(other : Object) : boolean
+ + equals(o : Object) : boolean
+ + getManufacturer() : String
+ + getModel() : String
+ + getVehicleId() : int
+ + hashCode() : int
+ + setManufacturer(manufacturer : String)
+ + setModel(model : String)
+ + setVehicleId(vehicleId : int)
+ + toString() : String
+ }
+}
+package com.iluwatar {
+ class SingleTableInheritance {
+ - vehicleService : VehicleService
+ + SingleTableInheritance(vehicleService : VehicleService)
+ + main(args : String[]) {static}
+ + run(args : String[])
+ }
+}
+SingleTableInheritance --> "-vehicleService" VehicleService
+VehicleService --> "-vehicleRepository" VehicleRepository
+PassengerVehicle --|> Vehicle
+TransportVehicle --|> Vehicle
+Car --|> PassengerVehicle
+Freighter --|> TransportVehicle
+PassengerVehicle --|> Vehicle
+Train --|> PassengerVehicle
+TransportVehicle --|> Vehicle
+Truck --|> TransportVehicle
+@enduml
\ No newline at end of file
diff --git a/single-table-inheritance/pom.xml b/single-table-inheritance/pom.xml
new file mode 100644
index 000000000000..159a683bea21
--- /dev/null
+++ b/single-table-inheritance/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+ com.iluwatar
+ java-design-patterns
+ 1.26.0-SNAPSHOT
+
+
+ single-table-inheritance
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
\ No newline at end of file
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/SingleTableInheritance.java b/single-table-inheritance/src/main/java/com/iluwatar/SingleTableInheritance.java
new file mode 100644
index 000000000000..01fbb37b828f
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/SingleTableInheritance.java
@@ -0,0 +1,93 @@
+package com.iluwatar;
+
+import com.iluwatar.entity.Car;
+import com.iluwatar.entity.Truck;
+import com.iluwatar.entity.Vehicle;
+import com.iluwatar.service.VehicleService;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Single Table Inheritance pattern :
+ *
+ * It maps each instance of class in an inheritance tree into a single table.
+ *
+ *
+ * In case of current project, in order to specify the Single Table Inheritance to Hibernate
+ * we annotate the main Vehicle root class with @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+ * due to which a single root Vehicle class table will be created
+ * in the database and it will have columns for all the fields of
+ * it's subclasses(Car, Freighter, Train, Truck).
+ * Additional to that, a new separate "vehicle_id" column would be added
+ * to the Vehicle table to save the type of the subclass object that
+ * is being stored in the database. This value is specified by the @DiscriminatorValue annotation
+ * value for each subclass in case of Hibernate.
+ *
+ * Below is the main Spring Boot Application class from where the Program Runs.
+ *
+ * It implements the CommandLineRunner to run the statements at the
+ * start of the application program.
+ *
+ */
+@SpringBootApplication
+@AllArgsConstructor
+public class SingleTableInheritance implements CommandLineRunner {
+
+ //Autowiring the VehicleService class to execute the business logic methods
+ private final VehicleService vehicleService;
+
+ /**
+ * The entry point of the Spring Boot Application.
+ *
+ * @param args program runtime arguments
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(SingleTableInheritance.class, args);
+ }
+
+ /**
+ * The starting point of the CommandLineRunner
+ * where the main program is run.
+ *
+ * @param args program runtime arguments
+ */
+ @Override
+ public void run(String... args) throws Exception {
+
+ Logger log = LoggerFactory.getLogger(SingleTableInheritance.class);
+
+ log.info("Saving Vehicles :- ");
+
+ // Saving Car to DB as a Vehicle
+ Vehicle vehicle1 = new Car("Tesla", "Model S", 4, 825);
+ Vehicle car1 = vehicleService.saveVehicle(vehicle1);
+ log.info("Vehicle 1 saved : {}", car1);
+
+ // Saving Truck to DB as a Vehicle
+ Vehicle vehicle2 = new Truck("Ford", "F-150", 3325, 14000);
+ Vehicle truck1 = vehicleService.saveVehicle(vehicle2);
+ log.info("Vehicle 2 saved : {}\n", truck1);
+
+
+ log.info("Fetching Vehicles :- ");
+
+ // Fetching the Car from DB
+ Car savedCar1 = (Car) vehicleService.getVehicle(vehicle1.getVehicleId());
+ log.info("Fetching Car1 from DB : {}", savedCar1);
+
+ // Fetching the Truck from DB
+ Truck savedTruck1 = (Truck) vehicleService.getVehicle(vehicle2.getVehicleId());
+ log.info("Fetching Truck1 from DB : {}\n", savedTruck1);
+
+ log.info("Fetching All Vehicles :- ");
+
+ // Fetching the Vehicles present in the DB
+ List allVehiclesFromDb = vehicleService.getAllVehicles();
+ allVehiclesFromDb.forEach(s -> log.info(s.toString()));
+ }
+}
\ No newline at end of file
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/Car.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/Car.java
new file mode 100644
index 000000000000..c8d3185fdce9
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/Car.java
@@ -0,0 +1,39 @@
+package com.iluwatar.entity;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * A class that extends the PassengerVehicle class
+ * and provides the concrete inheritance implementation of the Car.
+ *
+ * @see PassengerVehicle PassengerVehicle
+ * @see Vehicle Vehicle
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@DiscriminatorValue(value = "CAR")
+public class Car extends PassengerVehicle {
+
+ private int engineCapacity;
+
+ public Car(String manufacturer, String model, int noOfPassengers, int engineCapacity) {
+ super(manufacturer, model, noOfPassengers);
+ this.engineCapacity = engineCapacity;
+ }
+
+ // Overridden the toString method to specify the Vehicle object
+ @Override
+ public String toString() {
+ return "Car{"
+ + super.toString()
+ + '}';
+ }
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/Freighter.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/Freighter.java
new file mode 100644
index 000000000000..ce35f3df37df
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/Freighter.java
@@ -0,0 +1,41 @@
+package com.iluwatar.entity;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * A class that extends the TransportVehicle class
+ * and provides the concrete inheritance implementation of the Car.
+ *
+ * @see TransportVehicle TransportVehicle
+ * @see Vehicle Vehicle
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@DiscriminatorValue(value = "FREIGHTER")
+public class Freighter extends TransportVehicle {
+
+ private double flightLength;
+
+ public Freighter(String manufacturer, String model, int loadCapacity, double flightLength) {
+ super(manufacturer, model, loadCapacity);
+ this.flightLength = flightLength;
+ }
+
+ // Overridden the toString method to specify the Vehicle object
+ @Override
+ public String toString() {
+ return "Freighter{ "
+ + super.toString()
+ + " ,"
+ + "flightLength="
+ + flightLength
+ + '}';
+ }
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/PassengerVehicle.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/PassengerVehicle.java
new file mode 100644
index 000000000000..c27818a9a1d9
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/PassengerVehicle.java
@@ -0,0 +1,30 @@
+package com.iluwatar.entity;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * An abstract class that extends the Vehicle class
+ * and provides properties for the Passenger type of Vehicles.
+ *
+ * @see Vehicle
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public abstract class PassengerVehicle extends Vehicle {
+
+ private int noOfPassengers;
+
+ protected PassengerVehicle(String manufacturer, String model, int noOfPassengers) {
+ super(manufacturer, model);
+ this.noOfPassengers = noOfPassengers;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/Train.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/Train.java
new file mode 100644
index 000000000000..10a74f36ac5a
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/Train.java
@@ -0,0 +1,38 @@
+package com.iluwatar.entity;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * A class that extends the PassengerVehicle class
+ * and provides the concrete inheritance implementation of the Car.
+ *
+ * @see PassengerVehicle PassengerVehicle
+ * @see Vehicle Vehicle
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@DiscriminatorValue(value = "TRAIN")
+public class Train extends PassengerVehicle {
+
+ private int noOfCarriages;
+
+ public Train(String manufacturer, String model, int noOfPassengers, int noOfCarriages) {
+ super(manufacturer, model, noOfPassengers);
+ this.noOfCarriages = noOfCarriages;
+ }
+
+ // Overridden the toString method to specify the Vehicle object
+ @Override
+ public String toString() {
+ return "Train{"
+ + super.toString()
+ + '}';
+ }
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/TransportVehicle.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/TransportVehicle.java
new file mode 100644
index 000000000000..9f9c60516e88
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/TransportVehicle.java
@@ -0,0 +1,25 @@
+package com.iluwatar.entity;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * An abstract class that extends the Vehicle class
+ * and provides properties for the Transport type of Vehicles.
+ *
+ * @see Vehicle
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public abstract class TransportVehicle extends Vehicle {
+
+ private int loadCapacity;
+
+ protected TransportVehicle(String manufacturer, String model, int loadCapacity) {
+ super(manufacturer, model);
+ this.loadCapacity = loadCapacity;
+ }
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/Truck.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/Truck.java
new file mode 100644
index 000000000000..e389666e4dcc
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/Truck.java
@@ -0,0 +1,38 @@
+package com.iluwatar.entity;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * A class that extends the PassengerVehicle class
+ * and provides the concrete inheritance implementation of the Car.
+ *
+ * @see TransportVehicle TransportVehicle
+ * @see Vehicle Vehicle
+ */
+@Data
+@NoArgsConstructor
+@Entity
+@DiscriminatorValue(value = "TRUCK")
+public class Truck extends TransportVehicle {
+
+ private int towingCapacity;
+
+ public Truck(String manufacturer, String model, int loadCapacity, int towingCapacity) {
+ super(manufacturer, model, loadCapacity);
+ this.towingCapacity = towingCapacity;
+ }
+
+ // Overridden the toString method to specify the Vehicle object
+ @Override
+ public String toString() {
+ return "Truck{ "
+ + super.toString()
+ + ", "
+ + "towingCapacity="
+ + towingCapacity
+ + '}';
+ }
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/entity/Vehicle.java b/single-table-inheritance/src/main/java/com/iluwatar/entity/Vehicle.java
new file mode 100644
index 000000000000..901a37705455
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/entity/Vehicle.java
@@ -0,0 +1,54 @@
+package com.iluwatar.entity;
+
+import javax.persistence.DiscriminatorColumn;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * An abstract class that is the root of the Vehicle Inheritance hierarchy
+ * and basic provides properties for all the vehicles.
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode
+@Entity
+@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn(name = "VEHICLE_TYPE")
+public abstract class Vehicle {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int vehicleId;
+
+ private String manufacturer;
+
+ private String model;
+
+ protected Vehicle(String manufacturer, String model) {
+ this.manufacturer = manufacturer;
+ this.model = model;
+ }
+
+ @Override
+ public String toString() {
+ return "Vehicle{"
+ + "vehicleId="
+ + vehicleId
+ + ", manufacturer='"
+ + manufacturer
+ + '\''
+ + ", model='"
+ + model
+ + '}';
+ }
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/repository/VehicleRepository.java b/single-table-inheritance/src/main/java/com/iluwatar/repository/VehicleRepository.java
new file mode 100644
index 000000000000..5aec26c3aa95
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/repository/VehicleRepository.java
@@ -0,0 +1,14 @@
+package com.iluwatar.repository;
+
+import com.iluwatar.entity.Vehicle;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * A repository that is extending the JPA Repository
+ * to provide the default Spring DATA JPA methods for the Vehicle class.
+ */
+@Repository
+public interface VehicleRepository extends JpaRepository {
+
+}
diff --git a/single-table-inheritance/src/main/java/com/iluwatar/service/VehicleService.java b/single-table-inheritance/src/main/java/com/iluwatar/service/VehicleService.java
new file mode 100644
index 000000000000..4aeacd04824d
--- /dev/null
+++ b/single-table-inheritance/src/main/java/com/iluwatar/service/VehicleService.java
@@ -0,0 +1,71 @@
+package com.iluwatar.service;
+
+import com.iluwatar.entity.Vehicle;
+import com.iluwatar.repository.VehicleRepository;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * A service class that is used to provide the business logic
+ * for the Vehicle class and connect to the database to
+ * perform the CRUD operations on the root Vehicle class.
+ *
+ * @see Vehicle
+ */
+@Service
+@AllArgsConstructor
+public class VehicleService {
+
+ private final VehicleRepository vehicleRepository;
+
+ /**
+ * A method to save all the vehicles to the database.
+ *
+ * @param vehicle Vehicle bbject
+ * @see Vehicle
+ */
+ public Vehicle saveVehicle(Vehicle vehicle) {
+ return vehicleRepository.save(vehicle);
+ }
+
+ /**
+ * A method to get a specific vehicle from vehicle id.
+ *
+ * @param vehicleId Vehicle Id
+ * @see Vehicle
+ */
+ public Vehicle getVehicle(int vehicleId) {
+ return vehicleRepository.findById(vehicleId).orElse(null);
+ }
+
+ /**
+ * A method to get all the vehicles saved in the database.
+ *
+ * @see Vehicle
+ */
+ public List getAllVehicles() {
+ return vehicleRepository.findAll();
+ }
+
+ /**
+ * A method to update a vehicle in the database.
+ *
+ * @param vehicle Vehicle object
+ * @see Vehicle
+ */
+ public Vehicle updateVehicle(Vehicle vehicle) {
+ return vehicleRepository.save(vehicle);
+ }
+
+ /**
+ * A method to save all the vehicles to the database.
+ *
+ * @param vehicle Vehicle object
+ * @see Vehicle
+ */
+ public void deleteVehicle(Vehicle vehicle) {
+ vehicleRepository.delete(vehicle);
+ }
+
+}
diff --git a/single-table-inheritance/src/main/resources/application.properties b/single-table-inheritance/src/main/resources/application.properties
new file mode 100644
index 000000000000..e2d8176fde86
--- /dev/null
+++ b/single-table-inheritance/src/main/resources/application.properties
@@ -0,0 +1,11 @@
+
+# H2 Database Configuration
+spring.datasource.url=jdbc:h2:mem:sti
+spring.datasource.username=sa
+spring.datasource.password=password
+spring.datasource.driverClassName=org.h2.Driver
+spring.jpa.hibernate.ddl-auto=update
+
+#Uncomment the below properties to see the SQL being generated in backend
+#spring.jpa.show-sql=true
+#spring.jpa.properties.hibernate.format_sql=true
\ No newline at end of file