JPA + Hibernate @Inheritance - TABLE_PER_CLASS Example
March 01, 2023
On this page, we will learn to use JPA @Inheritance
annotation with TABLE_PER_CLASS strategy in our Hibernate application.
1. The
@Inheritance
annotation specifies the inheritance strategy to be used for an entity class hierarchy. The inheritance strategy can be JOINED, SINGLE_TABLE and TABLE_PER_CLASS.
2. In TABLE_PER_CLASS inheritance strategy, we map only the concrete classes of an inheritance hierarchy to tables. Each table defines all persistent states of the class, including the inherited state.
3. The
@Inheritance
annotation with TABLE_PER_CLASS strategy is specified at the root entity. Root class and subclass entity persist data in separate tables mapped with them. Subclass entity contains the inherited fields and its own fields.
4. To use TABLE_PER_CLASS inheritance, we need to create a root class and some subclasses. Root class is annotated with
@Entity
and @Inheritance
annotations. Root class persist data in a table mapped with it.
@Entity(name = "account") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Account { ------ }
@Entity(name = "credit_account") public class CreditAccount extends Account { ------ }
Complete Example
1. Technologies Used1. Java 19
2. Hibernate 6
3. Jakarta Persistence API 3
4. MySQL 5.5
2. pom.xml
<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.1.6.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>6.0.0.Alpha7</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> </dependencies>
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <persistence-unit name="com.concretepage"> <description>Procedure Demo</description> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" /> <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost/concretepage" /> <property name="jakarta.persistence.jdbc.user" value="root" /> <property name="jakarta.persistence.jdbc.password" value="cp" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit> </persistence>
Find the tables.
CREATE TABLE `account` ( `account_id` BIGINT(20) NOT NULL, `balance` DECIMAL(19,2) NULL DEFAULT NULL, `interestRate` DECIMAL(19,2) NULL DEFAULT NULL, `owner` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`account_id`) ) CREATE TABLE `credit_account` ( `account_id` BIGINT(20) NOT NULL, `balance` DECIMAL(19,2) NULL DEFAULT NULL, `interestRate` DECIMAL(19,2) NULL DEFAULT NULL, `owner` VARCHAR(255) NULL DEFAULT NULL, `creditLimit` DECIMAL(19,2) NULL DEFAULT NULL, PRIMARY KEY (`account_id`) ) CREATE TABLE `debit_account` ( `account_id` BIGINT(20) NOT NULL, `balance` DECIMAL(19,2) NULL DEFAULT NULL, `interestRate` DECIMAL(19,2) NULL DEFAULT NULL, `owner` VARCHAR(255) NULL DEFAULT NULL, `overdraftFee` DECIMAL(19,2) NULL DEFAULT NULL, PRIMARY KEY (`account_id`) )
5. Java Code
Find the root class.
Account.java
@Entity(name = "account") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Account { @Id @Column(name = "account_id") private Long id; @Column(name = "balance") private BigDecimal balance; @Column(name = "interestRate") private BigDecimal interestRate; @Column(name = "owner") private String owner; public Account(Long id, BigDecimal balance, BigDecimal interestRate, String owner) { this.id = id; this.balance = balance; this.interestRate = interestRate; this.owner = owner; } // Setters and Getters }
CreditAccount.java
@Entity(name = "credit_account") public class CreditAccount extends Account { @Column(name = "creditLimit") private BigDecimal creditLimit; public CreditAccount(Long id, BigDecimal balance, BigDecimal interestRate, String owner, BigDecimal creditLimit) { super(id, balance, interestRate, owner); this.creditLimit = creditLimit; } // Setters and Getters }
@Entity(name = "debit_account") public class DebitAccount extends Account { @Column(name = "overdraftFee") private BigDecimal overdraftFee; public DebitAccount(Long id, BigDecimal balance, BigDecimal interestRate, String owner, BigDecimal overdraftFee) { super(id, balance, interestRate, owner); this.overdraftFee = overdraftFee; } // Setters and Getters }
Now run the code.
HibernateUtil.java
public class HibernateUtil { private static final EntityManagerFactory emFactory; static { emFactory = Persistence.createEntityManagerFactory("com.concretepage"); } public static EntityManager getEntityManager(){ return emFactory.createEntityManager(); } }
public class Main { public static void main(String[] args) { EntityManager entityManager = HibernateUtil.getEntityManager(); entityManager.getTransaction().begin(); Account daccount = new Account(101L, BigDecimal.valueOf(150), BigDecimal.valueOf(1.2d), "Mahesh"); DebitAccount debitAccount = new DebitAccount(101L, BigDecimal.valueOf(150), BigDecimal.valueOf(1.2d), "Mahesh", BigDecimal.valueOf(50)); Account caccount = new Account(202L, BigDecimal.valueOf(1500), BigDecimal.valueOf(1.6d), "Krishn"); CreditAccount creditAccount = new CreditAccount(202L, BigDecimal.valueOf(1500), BigDecimal.valueOf(1.6d), "Krishn", BigDecimal.valueOf(1000)); entityManager.persist(daccount); entityManager.persist(caccount); entityManager.getTransaction().commit(); entityManager.clear(); entityManager.getTransaction().begin(); entityManager.persist(debitAccount); entityManager.persist(creditAccount); entityManager.getTransaction().commit(); entityManager.close(); } }
Hibernate: insert into account (balance, interestRate, owner, account_id) values (?, ?, ?, ?) Hibernate: insert into account (balance, interestRate, owner, account_id) values (?, ?, ?, ?) Hibernate: insert into debit_account (balance, interestRate, owner, overdraftFee, account_id) values (?, ?, ?, ?, ?) Hibernate: insert into credit_account (balance, interestRate, owner, creditLimit, account_id) values (?, ?, ?, ?, ?)
