In this tutorial we are going to implement table per sub class strategy in hibernate inheritance. For bettor understanding we are taking the same example (Card, Cheque and Payment classes) like previous tutorials table per class and table per concrete class.

Table per Sub Class in Hibernate :

We can choose this inheritance strategy, If we want to map a super class and its sub classes to its own tables in database. For this strategy each class in the hierarchy have their own table and each class data will be saved in respective tables in database.

In table per sub class strategy, when we save the sub class data then automatically the common data will be saved in the parent table.

Thus here  we have 3 tables in database : card_table , cheque_table and payment. When we save the Card and Cheque data the common data between the Card and Cheque  will be saved in payment table (super class). Note that here a foreign key relation should be existed in the sub and super class tables.

Table per Sub Class Example :

To achieve table per sub class strategy, we need to configure the sub classes with <joined-subclass> tag under the <class> tag in hbm.xml file.

Each sub class table has a foreign key column, and we need to represent the foreign key in hibernate with <key> tag.

Recommended :

Table per Class Strategy in Hibernate

Table per Concrete Class Strategy in Hibernate

When we save a sub class object, then hibernate prepares two insert commands and inserts super class properties and subclass properties into 2 separate tables.

 Classes hierarchy :

Table per ClassDatabase Schema :

[sql]
CREATE TABLE `payment` (
    `payid` INT(11) NOT NULL,
    `amount` DOUBLE NULL DEFAULT NULL,
    `paydate` DATE NULL DEFAULT NULL,
    PRIMARY KEY (`payid`)
)
COLLATE=’latin1_swedish_ci’
ENGINE=InnoDB;

CREATE TABLE `card_table` (
    `payid` INT(11) NULL DEFAULT NULL,
    `cardnumber` INT(11) NULL DEFAULT NULL,
    `cardtype` VARCHAR(50) NULL DEFAULT NULL,
    INDEX `FK_card_table_payment` (`payid`),
    CONSTRAINT `FK_card_table_payment` FOREIGN KEY (`payid`) REFERENCES `payment` (`payid`)
)
COLLATE=’latin1_swedish_ci’
ENGINE=InnoDB;

CREATE TABLE `cheque_table` (
    `payid` INT(11) NULL DEFAULT NULL,
    `chqnumber` INT(11) NULL DEFAULT NULL,
    `chqtype` VARCHAR(50) NULL DEFAULT NULL,
    INDEX `FK_cheque_table_payment` (`payid`),
    CONSTRAINT `FK_cheque_table_payment` FOREIGN KEY (`payid`) REFERENCES `payment` (`payid`)
)
COLLATE=’latin1_swedish_ci’
ENGINE=InnoDB;

[/sql]

Payment.java

[java]
package com.onlinetutorialspoint.hibernate.model;

import java.util.Date;

public class Payment {

    private int paymentId;
    private double amount;
    private Date paymentDate;

    public int getPaymentId() {
        return paymentId;
    }

    public void setPaymentId(int paymentId) {
        this.paymentId = paymentId;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public Date getPaymentDate() {
        return paymentDate;
    }

    public void setPaymentDate(Date paymentDate) {
        this.paymentDate = paymentDate;
    }

}

[/java]

Card.java

[java]
package com.onlinetutorialspoint.hibernate.model;

public class Card extends Payment {

    private int cardNumber;
    private String cardType;

    public int getCardNumber() {
        return cardNumber;
    }

    public void setCardNumber(int cardNumber) {
        this.cardNumber = cardNumber;
    }

    public String getCardType() {
        return cardType;
    }

    public void setCardType(String cardType) {
        this.cardType = cardType;
    }

}

[/java]

Cheque.java

[java]
package com.onlinetutorialspoint.hibernate.model;

public class Cheque extends Payment {

    private int chequeNumber;
    private String chequeType;

    public int getChequeNumber() {
        return chequeNumber;
    }

    public void setChequeNumber(int chequeNumber) {
        this.chequeNumber = chequeNumber;
    }

    public String getChequeType() {
        return chequeType;
    }

    public void setChequeType(String chequeType) {
        this.chequeType = chequeType;
    }

}

[/java]

payment.hbm.xml

[xml highlight=”8-17″]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.onlinetutorialspoint.hibernate.model.Payment" table="payment">
        <id name="paymentId" column="payid"/>
        <property name="amount"/>
        <property name="paymentDate" column="paydate" type="date"/>
        <joined-subclass name="com.onlinetutorialspoint.hibernate.model.Card" table="card_table">
            <key column="payid"/>
            <property name="cardNumber" column="cardnumber"/>
            <property name="cardType" column="cardtype"/>
        </joined-subclass>
        <joined-subclass name="com.onlinetutorialspoint.hibernate.model.Cheque" table="cheque_table">
            <key column="payid"/>
            <property name="chequeNumber" column="chqnumber"/>
            <property name="chequeType" column="chqtype"/>
        </joined-subclass>
    </class>
</hibernate-mapping>

[/xml]

PaymentDAO.java

[java]
package com.onlinetutorialspoint.hibernate.dao;

import com.onlinetutorialspoint.hibernate.model.Card;
import com.onlinetutorialspoint.hibernate.model.Cheque;

public interface PaymentDAO {

    public void saveCard(Card card);

    public void saveCheque(Cheque cheque);
}

[/java]

PaymentDAOImpl.java

[java]
package com.onlinetutorialspoint.hibernate.dao;

import com.onlinetutorialspoint.hibernate.model.Card;
import com.onlinetutorialspoint.hibernate.model.Cheque;
import com.onlinetutorialspoint.hibernate.util.HibernateUtil;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;

public class PaymentDAOImpl implements PaymentDAO {

    public void saveCard(Card card) {
        SessionFactory factory = HibernateUtil.getInstnce();
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        session.save(card);
        tx.commit();
        session.close();
        System.out.println("Card Inserted Successfully..");

    }

    public void saveCheque(Cheque cheque) {
        SessionFactory factory = HibernateUtil.getInstnce();
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        session.save(cheque);
        tx.commit();
        session.close();
        System.out.println("Cheque Inserted Successfully..");
    }

}

[/java]

PaymentDAOFactory.java

[java]
package com.onlinetutorialspoint.hibernate.dao;

public class PaymentDAOFactory {

    public static PaymentDAO getInstance() {
        return new PaymentDAOImpl();
    }
}

[/java]

Main.java

[java]

import com.onlinetutorialspoint.hibernate.dao.PaymentDAO;
import com.onlinetutorialspoint.hibernate.dao.PaymentDAOFactory;
import com.onlinetutorialspoint.hibernate.model.Card;
import com.onlinetutorialspoint.hibernate.model.Cheque;
import java.util.Date;

public class Main {

    public static void main(String[] args) {

        Card card = new Card();
        card.setPaymentId(110006);
        card.setPaymentDate(new Date());
        card.setAmount(20000);
        card.setCardNumber(661423);
        card.setCardType("MASTRO");
        PaymentDAO dao = PaymentDAOFactory.getInstance();
        dao.saveCard(card);

        System.out.println("=========================");

        Cheque cheque = new Cheque();
        cheque.setPaymentId(2256125);
        cheque.setPaymentDate(new Date());
        cheque.setAmount(80000);
        cheque.setChequeNumber(689523);
        cheque.setChequeType("ORDER");
        dao.saveCheque(cheque);
    }
}

[/java]

Output :

Hibernate: insert into payment (amount, paydate, payid) values (?, ?, ?) 
Hibernate: insert into card_table (cardnumber, cardtype, payid) values (?, ?, ?) Card Inserted Successfully.. 
========================= 
Hibernate: insert into payment (amount, paydate, payid) values (?, ?, ?) 
Hibernate: insert into cheque_table (chqnumber, chqtype, payid) values (?, ?, ?) 
Cheque Inserted Successfully..

By running the Main class, data can be saved in different tables like card_table, cheque_table and payment table. But we done save operation only on Card and Cheque objects.But the hibernate internally inserts the data in parent table by using the foreign key configuration in payment.hbm.xml file.

Database Output :

Table per sub class

Happy Learning 🙂