Table per Class is one of the Hibernate inheritance strategy. As we discussed in the previous tutorial Types of Inheritance Mapping Strategies in Hibernate.
In this tutorials, we are going to implement the Table per Class strategy in Hibernate using xml configuration. We can also implement the same example using hibernate annotations here is the example.
Hibernate Table per Class Strategy :
We can use the Table per Class strategy, if we want to store the data of all classes hierarchy into a single database table. For this strategy we can store all classes data in a single table.
Since all classes data in hierarchy would be saved in a single database table, to identify a particular class data, hibernate needs an extra column called discriminator. By using this discriminator column, we can easily find a particular class data in table.
So then, while creating the table in database, apart from all the required columns, we need to create an extra column which is discriminator.
Database Table :
[sql]
CREATE TABLE `payment` (
`payid` INT(11) NOT NULL,
`amount` DOUBLE NULL DEFAULT NULL,
`cardnumber` INT(11) NULL DEFAULT NULL,
`cardtype` VARCHAR(50) NULL DEFAULT NULL,
`chqnumber` INT(11) NULL DEFAULT NULL,
`chqtype` VARCHAR(50) NULL DEFAULT NULL,
`paydate` DATE NULL DEFAULT NULL,
`paymode` VARCHAR(50) NULL DEFAULT NULL COMMENT ‘Discriminator column’
)
COLLATE=’latin1_swedish_ci’
ENGINE=InnoDB;
[/sql]
In hbm.xml file we need to configure the Table per Class strategy. Each subclass of inheritance is mapped by using <subclass> tag. The discriminator is configured by using the <discriminator> tag. The only restriction with <discriminator> tag is, it should be added immediately after closing the <id> tag.
Example for Hibernate Table per Class :
[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=”5-6″]
<?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"/>
<discriminator column="paymode" type="string"/>
<property name="amount"/>
<property name="paymentDate" column="paydate" type="date"/>
<subclass name="com.onlinetutorialspoint.hibernate.model.Card" discriminator-value="cp">
<property name="cardNumber" column="cardnumber"/>
<property name="cardType" column="cardtype"/>
</subclass>
<subclass name="com.onlinetutorialspoint.hibernate.model.Cheque" discriminator-value="chp">
<property name="chequeNumber" column="chqnumber"/>
<property name="chequeType" column="chqtype"/>
</subclass>
</class>
</hibernate-mapping>
[/xml]
hibernate.cfg.xml
[xml]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/onlinetutorialspoint?zeroDateTimeBehavior=convertToNull</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<mapping resource="payment.hbm.xml"/>
</session-factory>
</hibernate-configuration>
[/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;
import org.hibernate.Transaction;
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(55661423);
card.setCardType("MASTRO");
PaymentDAO dao = PaymentDAOFactory.getInstance();
dao.saveCard(card);
System.out.println("=========================");
Cheque cheque = new Cheque();
cheque.setPaymentId(225612);
cheque.setPaymentDate(new Date());
cheque.setAmount(80000);
cheque.setChequeNumber(45689523);
cheque.setChequeType("ORDER");
dao.saveCheque(cheque);
}
}
[/java]
Output :
Hibernate: insert into payment (amount, paydate, cardnumber, cardtype, paymode, payid) values (?, ?, ?, ?, 'cp', ?) Card Inserted Successfully.. ========================= Hibernate: insert into payment (amount, paydate, chqnumber, chqtype, paymode, payid) values (?, ?, ?, ?, 'chp', ?) Cheque Inserted Successfully..
Database :
By running the above Main class, both Card and Cheque classes are stored in the same table payment. We can differentiate both Card and Cheque information by using the discriminator column.
Happy Learning 🙂