June 05, 2017

Implementing Inheritance in Hibernate

We will create a Mobile class, which is extended by two other classes. Both SamsungMobile and BlackberryMobile have one more variable samsungModelType and bbModel respectively.

1).
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name = "mobile_details")
public class Mobile {
    @Id @GeneratedValue
    private int mobileId;
    private String mobileName;
    //getters and setters
}

2).
import javax.persistence.Entity;
@Entity
public class SamsungMobile extends Mobile {
    private String samsungModelType;
    //getters and setters
}

3).
import javax.persistence.Entity;

@Entity
public class BlackberryMobile extends Mobile{
    public String bbModel;
    //getters and setters
}

4).
public class MobileTest {

    public static void main(String[] args) {
        Mobile mobile=new Mobile();
        mobile.setMobileName("Test Mobile Set");
       
        SamsungMobile samsung=new SamsungMobile();
        samsung.setMobileName("Samsung A series");
        samsung.setSamsungModelType("A5");
       
        BlackberryMobile blackberry=new BlackberryMobile();
        blackberry.setMobileName("Blackberry Curve Series");
        blackberry.setBbModel("C10");
       
        // create a session factory
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        // get the session from session factory
        Session savesession = sessionFactory.openSession();
        savesession.beginTransaction();
        // to save the object in hibernate       
        savesession.save(mobile);
        savesession.save(samsung);
        savesession.save(blackberry);
        savesession.getTransaction().commit();
        savesession.close();
    }
}


When you execute MobileTest, following queries are fired:
Hibernate: insert into mobile_details (mobileName, DTYPE, mobileId) values (?, 'Mobile', ?)
Hibernate: insert into mobile_details (mobileName, samsungModelType, DTYPE, mobileId) values (?, ?, 'SamsungMobile', ?)
Hibernate: insert into mobile_details (mobileName, bbModel, DTYPE, mobileId) values (?, ?, 'BlackberryMobile', ?)


Although we have marked SamsungMobile and BlackberryMobile as Entity class, but the hibernate has not created the seprate table, instead it has mapped the details in the base class table itself. This is because, by default hibernate use Single Table Strategy.



You can change the strategy, by added the @Inheritance annotation in the base class. e.g @Inheritance (strategy=InheritanceType.SINGLE_TABLE)

where, InheritanceType can be SINGLE_TABLE, TABLE_PER_CLASS or JOINED

mobile_details will have (DTYPE, mobileId, mobileName, samsungModelType, bbModel) columns with three rows having values (Mobile,1,Test Mobile Set,NULL,NULL), (SamsungMobile,2,Samsung A series,A5,NULL) and (BlackberryMobile,3,Blackberry Curve Series,NULL,C10)

where the column DTYPE contains the name of the entity class. Dtype is called Discriminator Type.

You can change the Discriminator Type, by adding @DiscriminatorColumn annotation in the base class. e.g:

@DiscriminatorColumn(name="mobile_type", discriminatorType=DiscriminatorType.STRING)

where, name will set the column name (which was previously the 'DType').
discriminatorType can be STRING, INTEGER or CHAR. By default STRING is the DiscriminatorType.

The discriminatorType by default stores the class name, but you can change it by adding @DiscriminatorValue annotation in the child class. e.g
@DiscriminatorValue ("Blackberry") and @DiscriminatorValue ("Samsung") can be added in BlackberryMobile and SamsungMobile respectively.

Now when you run MobileTest, it will fire below queries:
Hibernate: insert into mobile_details (mobileName, mobile_type, mobileId) values (?, 'Mobile', ?)
Hibernate: insert into mobile_details (mobileName, samsungModelType, mobile_type, mobileId) values (?, ?, 'Samsung', ?)
Hibernate: insert into mobile_details (mobileName, bbModel, mobile_type, mobileId) values (?, ?, 'Blackberry', ?)


mobile_details will have (mobile_type,mobileId,mobileName,samsungModelType,bbModel) columns with three rows:
(Mobile,1,Test Mobile Set,NULL,NULL)
(Samsung,2,Samsung A series,A5,NULL)
(Blackberry,3,Blackberry Curve Series,NULL,C10)


Example Of Inheritance With Table Per Class Strategy
@DiscriminatorColumn and @DiscriminatorValue are not needed in table per class strategy and you need to select strategy as InheritanceType.TABLE_PER_CLASS.

1).
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table(name = "mobile_details")
@Inheritance (strategy=InheritanceType.TABLE_PER_CLASS)
public class Mobile {
    @Id @GeneratedValue
    private int mobileId;
    private String mobileName;
    //getters and setters
}
2).
import javax.persistence.Entity;
@Entity
public class SamsungMobile extends Mobile {
    private String samsungModelType;
    //getters and setters
}

3).
import javax.persistence.Entity;
@Entity
public class BlackberryMobile extends Mobile{
    public String bbModel;
    //getters and setters
}
When you execute MobileTest, following queries will be fired.
Hibernate: insert into mobile_details (mobileName, mobileId) values (?, ?)
Hibernate: insert into SamsungMobile (mobileName, samsungModelType, mobileId) values (?, ?, ?)
Hibernate: insert into BlackberryMobile (mobileName, bbModel, mobileId) values (?, ?, ?)
Separate tables for each class will be created. Parent class properties are inherited and they form the separate columns in the child tables.


Example Of Inheritance With Joined Strategy
We need to set strategy as InheritanceType.JOINED in the parent class.

When you run the MobileTest class after adding below line in parent Mobile class:
@Inheritance (strategy=InheritanceType.JOINED)
These queries will be executed:
Hibernate: insert into mobile_details (mobileName, mobileId) values (?, ?)
Hibernate: insert into mobile_details (mobileName, mobileId) values (?, ?)
Hibernate: insert into SamsungMobile (samsungModelType, mobileId) values (?, ?)
Hibernate: insert into mobile_details (mobileName, mobileId) values (?, ?)
Hibernate: insert into BlackberryMobile (bbModel, mobileId) values (?, ?)
  • mobile_details table will have two columns (mobileId, mobileName) and three rows: (1,Test Mobile Set), (2,Samsung A series) and (3,Blackberry Curve Series)
  • SamsungMobile table will have two columns (samsungModelType,mobileId) and one row:(A5,2)
  • BlackberryMobile table will have two columns (bbModel,mobileId) and one row:(C10,3)
-K Himaanshu Shuklaa..

No comments:

Post a Comment