Friday, 26 December 2014

Inheritance in hibernate


Let’s write a simple application using inheritance and see how hibernate handles inheritance. In later posts we see how to tweak default inheritance strategy handled by Hibernate.

Let’s say I had a product class and all the products like Books, laptops, cameras etc. all implements Product class like below.

package myFirstHibernate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Product {
  @Id @GeneratedValue
  int id;
  private int noOfProducts;

  public int getNoOfProducts() {
    return noOfProducts;
  }

  public void setNoOfProducts(int noOfProducts) {
    this.noOfProducts = noOfProducts;
  }
  
}

package myFirstHibernate;

import javax.persistence.Entity;

@Entity
public class Book extends Product{
  private String title;
  private String author;
  
  public String getTitle() {
    return title;
  }
  
  public void setTitle(String title) {
    this.title = title;
  }
  
  public String getAuthor() {
    return author;
  }
  
  public void setAuthor(String author) {
    this.author = author;
  }
  
}


package myFirstHibernate;

import javax.persistence.Entity;

@Entity
public class Laptop extends Product {
  private String brand;
  private String model;
  
  public String getBrand() {
    return brand;
  }
  
  public void setBrand(String brand) {
    this.brand = brand;
  }
  
  public String getModel() {
    return model;
  }
  
  public void setModel(String model) {
    this.model = model;
  }
  
}


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>
  
    <!--  Database Connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost/sample</property>
    <property name="connection.username">root</property>
    <property name="connection.password">tiger</property>
    
    <!-- Enable the logging of all the generated SQL statements to the console -->
    <property name="show_sql">true</property>
    
    <!-- Format the generated SQL statement to make it more readable, -->
    <property name="format_sql">false</property>
    
    <!-- Hibernate will put comments inside all generated SQL statements to hint what’s the generated SQL trying to do -->
    <property name="use_sql_comments">false</property>
    
    <!-- This property makes Hibernate generate the appropriate SQL for the chosen database. -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    
    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">create</property>
    
    <!-- mappings for annotated classes -->
    <mapping class="myFirstHibernate.Product" />
    <mapping class="myFirstHibernate.Book" />
     <mapping class="myFirstHibernate.Laptop" />
    
  </session-factory>
  
</hibernate-configuration>

package myFirstHibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class TestInheritance {
  
  /* Step 1: Create session factory */
  private static SessionFactory getSessionFactory() {
    Configuration configuration = new Configuration().configure();
    StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
    applySettings(configuration.getProperties());
    SessionFactory factory = configuration.buildSessionFactory(builder.build());
        return factory;
    }
  
  public static void main(String args[]){
    Product prod = new Product();
    Book book = new Book();
    Laptop laptop = new Laptop();
    
    prod.setNoOfProducts(2234);
    
    book.setAuthor("eckhart tolle");
    book.setNoOfProducts(1234);
    book.setTitle("The Power of Now");
    
    laptop.setBrand("Dell");
    laptop.setModel("Alienware 17 Laptop");
    laptop.setNoOfProducts(1000);
    
    /* To persist data */
    SessionFactory sessionFactory = getSessionFactory();
    Session session = sessionFactory.openSession();
    session.beginTransaction();
    session.save(prod);
    session.save(book);
    session.save(laptop);
    session.getTransaction().commit();
    session.close(); 
  }
}

Run TestInheritance class, you will get output like below.

Hibernate: drop table if exists Product
Hibernate: create table Product (DTYPE varchar(31) not null, id integer not null auto_increment, noOfProducts integer not null, author varchar(255), title varchar(255), brand varchar(255), model varchar(255), primary key (id))
Dec 22, 2014 10:20:48 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into Product (noOfProducts, DTYPE) values (?, 'Product')
Hibernate: insert into Product (noOfProducts, author, title, DTYPE) values (?, ?, ?, 'Book')
Hibernate: insert into Product (noOfProducts, brand, model, DTYPE) values (?, ?, ?, 'Laptop')


MySQL table structure looks like below.

mysql> describe product;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| DTYPE        | varchar(31)  | NO   |     | NULL    |                |
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| noOfProducts | int(11)      | NO   |     | NULL    |                |
| author       | varchar(255) | YES  |     | NULL    |                |
| title        | varchar(255) | YES  |     | NULL    |                |
| brand        | varchar(255) | YES  |     | NULL    |                |
| model        | varchar(255) | YES  |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+
7 rows in set (0.04 sec)

mysql> select * from product;
+---------+----+--------------+---------------+------------------+-------+---------------------+
| DTYPE   | id | noOfProducts | author        | title            | brand | model               |
+---------+----+--------------+---------------+------------------+-------+---------------------+
| Product |  1 |         2234 | NULL          | NULL             | NULL  | NULL                |
| Book    |  2 |         1234 | eckhart tolle | The Power of Now | NULL  | NULL                |
| Laptop  |  3 |         1000 | NULL          | NULL             | Dell  | Alienware 17 Laptop |
+---------+----+--------------+---------------+------------------+-------+---------------------+
3 rows in set (0.00 sec)



As you observe above, There is only one table created for all the three classes Product, Book, Laptop. This is called Single table strategy of hibernate inheritance. This is the default strategy of hibernate inheritance.

In single table strategy, all the field names of classes and sub classes are becomes columns names of the table. In addition to this, you can see one more column “DTYPE” (stands for Discriminator column) is added to product table, it specifies, this row belongs to particular class.

“DTYPE” = “Product” specifies this row is of type class Product.
“DTYPE” = “Book” specifies this row is of type class Book.
“DTYPE” = “Laptop” specifies this row is of type class Laptop.


Prevoius                                                 Next                                                 Home

No comments:

Post a Comment