Blog Image

Table Per Sub Class Using Annotation  

In this blog, we show you how to use Hibernate to implement "Inheritance Mapping Table Per Sub Class Using Annotation relationship by using jpa Annotation approach. This is the most common use case we often encounter in an Application Development.

Below is the example for Inheritance Mapping Table Per Sub Class Annotation approach.

Lets see Inheritance Mapping example:
Technologies used :-
1) java (1.8).
2) maven (3.5.2).
3) hibernate (5.2.12).
4) MySql (5.7.21).

Below is the table structure.
Execute this query for creating tables in Database(MySql).
CREATE TABLE `payment` (
  `payment_no` int(11) NOT NULL,
  `amount` float DEFAULT NULL,
  `merchant_nm` varchar(255) DEFAULT NULL,
  `payment_dt` datetime DEFAULT NULL,
  PRIMARY KEY (`payment_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

CREATE TABLE `card_payment` (
  `bank_nm` varchar(255) DEFAULT NULL,
  `card_holder_nm` varchar(255) DEFAULT NULL,
  `card_no` int(11) DEFAULT NULL,
  `card_payment_no` int(11) NOT NULL,
  PRIMARY KEY (`card_payment_no`),
  CONSTRAINT `FK3vlr2fwmf9e5drkn5gectvfy7` FOREIGN KEY (`card_payment_no`) REFERENCES `payment` (`payment_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

CREATE TABLE `cheque_payment` (
  `cheque_issue_dt` datetime DEFAULT NULL,
  `cheque_issue_nm` varchar(255) DEFAULT NULL,
  `cheque_no` int(11) DEFAULT NULL,
  `cheque_payment_no` int(11) NOT NULL,
  PRIMARY KEY (`cheque_payment_no`),
  CONSTRAINT `FK3mv8rjllf8cqhrv3euj18c6em` FOREIGN KEY (`cheque_payment_no`) REFERENCES `payment` (`payment_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

Project Structure

Below is the maven project structure with packages and java/resource files.
Entity Classes
CardPayment.java
package com.tpsc.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "card_payment")
@PrimaryKeyJoinColumn(name = "card_payment_no")
public class CardPayment extends Payment {
    @Column(name = "card_no")
    protected int cardNo;
    @Column(name = "bank_nm")
    protected String bankName;
    @Column(name = "card_holder_nm")
    protected String cardHolderName;

    public int getCardNo() {
        return cardNo;
    }

    public void setCardNo(int cardNo) {
        this.cardNo = cardNo;
    }

    public String getBankName() {
        return bankName;
    }

    public void setBankName(String bankName) {
        this.bankName = bankName;
    }

    public String getCardHolderName() {
        return cardHolderName;
    }

    public void setCardHolderName(String cardHolderName) {
        this.cardHolderName = cardHolderName;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((bankName == null) ? 0 : bankName.hashCode());
        result = prime * result + ((cardHolderName == null) ? 0 : cardHolderName.hashCode());
        result = prime * result + cardNo;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        CardPayment other = (CardPayment) obj;
        if (bankName == null) {
            if (other.bankName != null)
                return false;
        } else if (!bankName.equals(other.bankName))
            return false;
        if (cardHolderName == null) {
            if (other.cardHolderName != null)
                return false;
        } else if (!cardHolderName.equals(other.cardHolderName))
            return false;
        if (cardNo != other.cardNo)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "CardPayment [cardNo=" + cardNo + ", bankName=" + bankName + ", cardHolderName=" + cardHolderName
                + ", paymentNo=" + paymentNo + ", paymentDate=" + paymentDate + ", merchantName=" + merchantName
                + ", amount=" + amount + "]";
    }
}
ChequePayment.java
package com.tpsc.entities;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "cheque_payment")
@PrimaryKeyJoinColumn(name = "cheque_payment_no")
public class ChequePayment extends Payment {
    @Column(name = "cheque_no")
    protected int chequeNo;
    @Column(name = "cheque_issue_dt")
    protected Date chequeIssueDate;
    @Column(name = "cheque_issue_nm")
    protected String chequeIssueName;

    public int getChequeNo() {
        return chequeNo;
    }

    public void setChequeNo(int chequeNo) {
        this.chequeNo = chequeNo;
    }

    public Date getChequeIssueDate() {
        return chequeIssueDate;
    }

    public void setChequeIssueDate(Date chequeIssueDate) {
        this.chequeIssueDate = chequeIssueDate;
    }

    public String getChequeIssueName() {
        return chequeIssueName;
    }

    public void setChequeIssueName(String chequeIssueName) {
        this.chequeIssueName = chequeIssueName;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((chequeIssueDate == null) ? 0 : chequeIssueDate.hashCode());
        result = prime * result + ((chequeIssueName == null) ? 0 : chequeIssueName.hashCode());
        result = prime * result + chequeNo;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        ChequePayment other = (ChequePayment) obj;
        if (chequeIssueDate == null) {
            if (other.chequeIssueDate != null)
                return false;
        } else if (!chequeIssueDate.equals(other.chequeIssueDate))
            return false;
        if (chequeIssueName == null) {
            if (other.chequeIssueName != null)
                return false;
        } else if (!chequeIssueName.equals(other.chequeIssueName))
            return false;
        if (chequeNo != other.chequeNo)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "ChequePayment [chequeNo=" + chequeNo + ", chequeIssueDate=" + chequeIssueDate + ", chequeIssueName="
                + chequeIssueName + ", paymentNo=" + paymentNo + ", paymentDate=" + paymentDate + ", merchantName="
                + merchantName + ", amount=" + amount + "]";
    }
}
Payment.java
package com.tpsc.entities;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
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 javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "payment")
@Inheritance(strategy = InheritanceType.JOINED)
public class Payment implements Serializable {
    @Id
    @Column(name="payment_no")
    @GeneratedValue(strategy=GenerationType.AUTO)
    protected int paymentNo;
    @Column(name="payment_dt")
    protected Date paymentDate;
    @Column(name="merchant_nm")
    protected String merchantName;
    @Column(name="amount")
    protected float amount;

    public int getPaymentNo() {
        return paymentNo;
    }

    public void setPaymentNo(int paymentNo) {
        this.paymentNo = paymentNo;
    }

    public Date getPaymentDate() {
        return paymentDate;
    }

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

    public String getMerchantName() {
        return merchantName;
    }

    public void setMerchantName(String merchantName) {
        this.merchantName = merchantName;
    }

    public float getAmount() {
        return amount;
    }

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

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Float.floatToIntBits(amount);
        result = prime * result + ((merchantName == null) ? 0 : merchantName.hashCode());
        result = prime * result + ((paymentDate == null) ? 0 : paymentDate.hashCode());
        result = prime * result + paymentNo;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Payment other = (Payment) obj;
        if (Float.floatToIntBits(amount) != Float.floatToIntBits(other.amount))
            return false;
        if (merchantName == null) {
            if (other.merchantName != null)
                return false;
        } else if (!merchantName.equals(other.merchantName))
            return false;
        if (paymentDate == null) {
            if (other.paymentDate != null)
                return false;
        } else if (!paymentDate.equals(other.paymentDate))
            return false;
        if (paymentNo != other.paymentNo)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Payment [paymentNo=" + paymentNo + ", paymentDate=" + paymentDate + ", merchantName=" + merchantName
                + ", amount=" + amount + "]";
    }
}
SessionFactoryRegistry.java
package com.tpsc.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class SessionFactoryRegistry {
    private static SessionFactory sessionFactory;

    static {
        try {
            sessionFactory = new MetadataSources(new StandardServiceRegistryBuilder().configure().build())
                    .getMetadataBuilder().build().buildSessionFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static SessionFactory getSessionFactory() {

        return sessionFactory;
    }

    public static void closeSessionFactory() {
        if (sessionFactory != null) {
            sessionFactory.close();
            sessionFactory = null;
        }
    }
}
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">;
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">welcome1</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/inheritance_mapping</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="current_session_context_class">thread</property>
               
        <mapping class="com.tpsc.entities.Payment"/>
        <mapping class="com.tpsc.entities.CardPayment"/>
        <mapping class="com.tpsc.entities.ChequePayment"/>
    </session-factory>
</hibernate-configuration>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">;
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.otm.configure</groupId>
  <artifactId>Table-Per-Sub-Class-Annotation</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>Table-Per-Sub-Class-Annotation</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>;

  <properties>
        <maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
        <javaee-api.version>6.0</javaee-api.version>
        <javax.servlet.version>3.1.0</javax.servlet.version>
    </properties>

  <dependencies>
        <dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>hibernate-core</artifactId>
              <version>5.2.12.Final</version>
        </dependency>
        <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.34</version>
        </dependency>    
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packagi... -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.7.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.20.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
Test.java
package com.tpsc.test;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.tpsc.entities.CardPayment;
import com.tpsc.entities.ChequePayment;
import com.tpsc.entities.Payment;
import com.tpsc.util.SessionFactoryRegistry;

public class Test {
    public static void main(String[] args) {
        SessionFactory sessionFactory = null;
        Transaction transaction = null;
        Session session = null;
        boolean flag = false;
        Payment payment = null;
        CardPayment cardPayment = null;
        ChequePayment chequePayment = null;
        try {
            sessionFactory = SessionFactoryRegistry.getSessionFactory();
            session = sessionFactory.getCurrentSession();
            transaction = session.beginTransaction();

            payment = new Payment();
            payment.setPaymentNo(1);
            payment.setPaymentDate(new Date());
            payment.setMerchantName("Big Bazar");
            payment.setAmount(1000);
            session.save(payment);

            cardPayment = new CardPayment();
            cardPayment.setPaymentNo(2);
            cardPayment.setPaymentDate(new Date());
            cardPayment.setMerchantName("Central");
            cardPayment.setAmount(2000);
            cardPayment.setCardNo(82398);
            cardPayment.setBankName("ICICI");
            cardPayment.setCardHolderName("Rose");
            session.save(cardPayment);

            chequePayment = new ChequePayment();
            chequePayment.setChequeNo(3);
            chequePayment.setPaymentDate(new Date());
            chequePayment.setMerchantName("Shoppers Stop");
            chequePayment.setAmount(3000);
            chequePayment.setChequeNo(2938928);
            chequePayment.setChequeIssueDate(new Date());
            chequePayment.setChequeIssueName("Jack");
            session.save(chequePayment);

            payment = session.get(Payment.class, 10);
            System.out.println(payment);          

            cardPayment = session.get(CardPayment.class, 11);
            System.out.println(cardPayment);          

            chequePayment = session.get(ChequePayment.class, 12);
            System.out.println(chequePayment);          

            payment = (Payment) session.get(CardPayment.class, 11);
            System.out.println(payment);

            payment = (Payment) session.get(ChequePayment.class, 12);
            System.out.println(payment);

            payment = session.get(Payment.class, 10);
            System.out.println(payment);

            cardPayment = session.get(CardPayment.class, 11);
            System.out.println(cardPayment);

            chequePayment = session.get(ChequePayment.class, 12);
            System.out.println(chequePayment);

            flag = true;
        } finally {
            if (transaction != null) {
                if (flag) {
                    transaction.commit();
                } else {
                    transaction.rollback();
                }
            }
            SessionFactoryRegistry.closeSessionFactory();
        }
    }
}


Please find attached the Table_Per_Sub_Class_Annotation.zip as an maven project as a reference. Feel free to pass your comments in the blog.

About author

User Image
Sriman

A software developer on JDK and JEE platform. I am passionate about Java technology and always an explorer and learner in new technologies in Java. I have experience on Open Source technologies like Struts, Spring, Jsf etc.. and even strong knowledge on Integration/Distributed world like Ejb, Web Services and Restful Services.

0

-Comments

Be the first person to write a comment for this Blog
Load More

No More Comments

Leave a Comment

Your comment has been posted and will appear soon.