Table per Class Hierarchy Using Annotation
In our previous tutorial we got introduced to Inheritance Mapping In Hibernate, In this article I will explain you about Table per Class Hierarchy Inheritance mapping. By this inheritance strategy, we can map the whole hierarchy in a single table. Here, an extra column otherwise known as discriminator column is created in the table to identify the class. In the table, for each record some columns will be empty; those columns for which the particular Java class does not have fields.
The above is the Hierarchy of classes involved. Here Employee is the super class for PermanentEmployee and ContractEmployee classes. Now Let us create Java classes for the above hierarchy to implement
Entity class
File: Employee.java
package entity;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
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 = "EMPLOYEE")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue(value = "")
public class Employee {
@Id
@GeneratedValue
@Column(name = "EMPID")
private int empID;
@Column(name = "EMP_NAME")
private String empName;
public int getEmpID() {
return empID;
}
public String getEmpName() {
return empName;
}
public void setEmpID(int empID) {
this.empID = empID;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
In case of table per class hierarchy a discriminator column is added by the hibernate framework that specifies the type of the record. It is mainly used to identify which derived class object have been saved in the table (see Database screen shot for better understanding). To specify this, following annotation where used in Super class entity.
@Inheritance – Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy.
@DiscriminatorColumn – Is used to define the discriminator column for the SINGLE_TABLE and JOINED inheritance mapping strategies. The strategy and the discriminator column are only specified in the root of an entity class hierarchy or sub hierarchy in which a different inheritance strategy is applied
If the @DiscriminatorColumn annotation is missing, and a discriminator column is required, the name of the discriminator column defaults to “DTYPE” and the discriminator type to DiscriminatorType.STRING.
@DiscriminatorValue – Is used to specify the value of the discriminator column for entities of the given type. The DiscriminatorValue annotation can only be specified on a concrete entity class. If the DiscriminatorValue annotation is not specified and a discriminator column is used, a provider-specific function will be used to generate a value representing the entity type. If the DiscriminatorType is STRING, the discriminator value default is the entity name.
The inheritance strategy and the discriminator column are only specified in the root of an entity class hierarchy or subhierarchy in which a different inheritance strategy is applied. The discriminator value, if not defaulted, should be specified for each entity class in the hierarchy.
File: PermanentEmployee.java
package entity;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "EMPLOYEE")
@DiscriminatorValue("Permanent Employee")
public class PermanentEmployee extends Employee {
@Column(name = "COMPANY_NAME")
private String companyName;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
}
PermanentEmployee class is child of Employee class. Thus while specifying the mappings, we used @DiscriminatorValue to specify discriminator value. In our case “Permanent Employee” will be persisted in discriminator column.
File: ContractEmployee.java
package entity;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "EMPLOYEE")
@DiscriminatorValue("Contract Employee")
public class ContractEmployee extends Employee {
@Column(name = "CONTRACTOR_NAME")
private String contractorName;
public String getContractorName() {
return contractorName;
}
public void setContractorName(String contractorName) {
this.contractorName = contractorName;
}
}
Hibernate Configuration file
oracle.jdbc.driver.OracleDriver system admin jdbc:oracle:thin:@xxx.x.x.x:1521:XE org.hibernate.dialect.Oracle10gDialect true create
The hbm2ddl.auto property is defined for creating automatic table in the database.
Client program
Create the class that stores the persistent object in this class, we are simply storing the employee objects in the database.
package util;
import entity.ContractEmployee;
import entity.PermanentEmployee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {
public static void main(String[] args) {
Configuration cf = new Configuration().configure("hibernate.cfg.xml");
StandardServiceRegistryBuilder srb = new StandardServiceRegistryBuilder();
srb.applySettings(cf.getProperties());
ServiceRegistry sr = srb.build();
SessionFactory sf = cf.buildSessionFactory(sr);
Session session = sf.openSession();
PermanentEmployee p1 = new PermanentEmployee();
p1.setEmpID(1);
p1.setEmpName("Ameer");
p1.setCompanyName("CTS");
PermanentEmployee p2 = new PermanentEmployee();
p2.setEmpID(2);
p2.setEmpName("Lourde");
p2.setCompanyName("TCS");
// create two objects of ContractEmployee
ContractEmployee t1 = new ContractEmployee();
t1.setEmpID(3);
t1.setEmpName("Prabhu");
t1.setContractorName("ABD Consultancy");
ContractEmployee t2 = new ContractEmployee();
t2.setEmpID(4);
t2.setEmpName("Badru");
t2.setContractorName("MN Consultancy");
Transaction tx = session.beginTransaction();
session.save(p1);
session.save(p2);
session.save(t1);
session.save(t2);
tx.commit();
System.out.println("Object saved successfully !");
session.close();
sf.close();
}
}
Eclipse Console
Database output
Hibernate update query example
In previous article we learnt to implement Hibernate delete Query example in Eclipse, in this article I will implement a program to update an object which is already persisted in the database.
Project Structure
Entity class
package entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "STUDENT")
public class StudentEntity {
@Id
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "DEPARTMENT")
private String department;
@Column(name = "COLLEGE")
private String college;
// Create Getters and Setters
}
Note: I have explained about every annotations used in the above file in the article Generic Hibernate Application Requirements
Hibernate Configuration file
File: hibernate.cfg.xml
oracle.jdbc.driver.OracleDriver system admin jdbc:oracle:thin:@127.0.0.1:1521:XE org.hibernate.dialect.Oracle10gDialect true update
Hibernate Utility
package util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import model.Student;
public class HibernateUtil {
public static void main(String[] args) {
Configuration cf = new Configuration().configure("hibernate.cfg.xml");
StandardServiceRegistryBuilder srb = new StandardServiceRegistryBuilder();
srb.applySettings(cf.getProperties());
ServiceRegistry sr = srb.build();
SessionFactory sf = cf.buildSessionFactory(sr);
Session session = sf.openSession();
Student std = (Student) session.load(Student.class, new Integer(2));
Transaction tx = session.beginTransaction();
// std.setId(3); // We Should not update "id"
std.setName("Ameer");
std.setCollege("PSG");
tx.commit(); // Update method will be called implicitly.
System.out.println("Object Updated successfully !");
session.close();
sf.close();
}
}
Hibernate Cache
- Whenever an object is loaded from database, hibernate stores the loaded object in cache memory which works in session scope.
- Now if we do any modifications to the loaded object, then these modification are stored only in the object maintained by cache memory. Even if we modify the loaded object for multiple times then also the modifications will be stored only in the cached object.
- But once we call transactions
commit()method then hibernate will check whether there are any changes between the object present in the database and the object stored in the cache, now the if changes exists then hibernate will automatically call its update method internally and updates the student object in database.
Program Explanation
- Line no 28: We should not update id, because we have loaded the object from the database only using this id member variable (See line no 25). So if we update this field, then hibernate will throws NonUniqueObjectException.
- At line no 29, I have updated
nameproperty of student object. - Line no 31: So once
commit()method is triggered from program, then hibernate will automatically call update method internally and updates the student object.
Data in DB before running the program
Run it – Eclipse Console
Data in DB after running the program
Hibernate Delete Query example
In previous article we learnt to implement Hibernate Select Query example in Eclipse, In this article I will implement an example on delete the object from the database(Delete Query) using Hibernate.
Project Structure
Entity class
package entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "STUDENT")
public class StudentEntity {
@Id
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "DEPARTMENT")
private String department;
@Column(name = "COLLEGE")
private String college;
// Create Getters and Setters
}
Note: I have explained about every annotations used in the above file in the article Generic Hibernate Application Requirements
Hibernate Configuration file
Create a new XML file and give this new configuration file the default name hibernate.cfg.xmland place it src directory of your project.
File: hibernate.cfg.xml
oracle.jdbc.driver.OracleDriver system admin jdbc:oracle:thin:@xxx.x.x.x:1521:XE org.hibernate.dialect.Oracle10gDialect true update
Hibernate Utility
package util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import entity.StudentEntity;
public class HibernateUtil {
public static void main(String[] args) {
Configuration cf = new Configuration().configure("hibernate.cfg.xml");
StandardServiceRegistryBuilder srb = new StandardServiceRegistryBuilder();
srb.applySettings(cf.getProperties());
ServiceRegistry sr = srb.build();
SessionFactory sf = cf.buildSessionFactory(sr);
Session session = sf.openSession();
StudentEntity std = (StudentEntity) session.load(StudentEntity.class, new Integer(2));
Transaction tx = session.beginTransaction();
session.delete(std);
tx.commit();
System.out.println("Object Deleted successfully !");
session.close();
sf.close();
}
}
In the above program we are deleting an object, which is already persisted (inserted) in the database; So in order to delete an persisted object, we need to load that object from the database and pass that object to the delete() method of Session interface, now hibernate delete that object whenever the transaction is committed.
In the article Steps to be followed to use Hibernate in Java, I have explained the configuration/code used in above program in detail.
Data in DB before running the program
Run it – Eclipse Console
Data in DB after running the program
Hibernate Select Query
In previous article we learnt to implement Hibernate 4 Insert Query example in Eclipse, In this article I will implement an example on loading the object from the database(Select Query) using Hibernate.
Project Structure
Entity class
package entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "STUDENT")
public class StudentEntity {
@Id
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "DEPARTMENT")
private String department;
@Column(name = "COLLEGE")
private String college;
// Create Getters and Setters
}
Note: I have explained about every annotations used in the above file in the article Generic Hibernate Application Requirements
Hibernate Configuration file
Create a new XML file and give this new configuration file the default name hibernate.cfg.xmland place it src directory of your project.
File: hibernate.cfg.xml
oracle.jdbc.driver.OracleDriver system admin jdbc:oracle:thin:@xxx.x.x.x:1521:XE org.hibernate.dialect.Oracle10gDialect true update
Hibernate Utility
package util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import entity.StudentEntity;
public class HibernateUtil {
public static void main(String[] args) {
Configuration cf = new Configuration().configure("hibernate.cfg.xml");
StandardServiceRegistryBuilder srb = new StandardServiceRegistryBuilder();
srb.applySettings(cf.getProperties());
ServiceRegistry sr = srb.build();
SessionFactory sf = cf.buildSessionFactory(sr);
Session session = sf.openSession();
StudentEntity std = (StudentEntity) session.load(StudentEntity.class, new Integer(1));
// For loading Transaction object is not necessary
System.out.println("Loaded object Student name is: " + std.getName());
System.out.println("Object Loaded successfully.....!!");
session.close();
sf.close();
}
}
In the article Steps to be followed to use Hibernate in Java, I have explained the configuration/code used in above program in detail.
Data in Database
Run it – Eclipse Console
Note
In hibernate we have 2 methods to load the object from the database, they are get and load. To know the difference between get and load method read the article here.