Hibernate
INHERITANCE AND RELATIONAL MAPPINGS
- BY GAURAV KUMAR
Inheritance
 Java is an object oriented language. It is possible to implement Inheritance in Java. Inheritance is one
of the most visible facets of Object-relational mismatch. Object oriented systems can model both “is
a” and “has a” relationship. Relational model supports only “has a” relationship between two entities.
Hibernate can help you map such Objects with relational tables. But you need to choose certain
mapping strategy based on your needs.
One Table Per Class Hierarchy
Suppose we have a class Person with subclass Employee. The properties of each class are:
• class Person - firstname - lastname
• class Employee - joining_date - department_name
In One Table per Class Hierarchy scheme, we store all the class hierarchy in a single SQL table. A discriminator
is a key to uniquely identify the base type of the class hierarchy.
Following are the advantages and disadvantages of One Table per Class Hierarchy scheme.
Advantage
This hierarchy offers the best performance even for in the deep hierarchy since single select may suffice.
Disadvantage
Changes to members of the hierarchy require column to be altered, added or removed from the table.
One Table Per Class Hierarchy
Example:-
package com.chaetu.training;
import javax.persistence.*;
@Entity
@Table(name = "PERSON")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="discriminator",
discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
public class Person {
@Id
@GeneratedValue
@Column(name = "PERSON_ID")
private Long personId;
@Column(name = "FIRSTNAME")
private String firstname;
@Column(name = "LASTNAME")
private String lastname;
// Constructors and Getter/Setter methods,
}
One Table Per Class Hierarchy
The Person class is the root of hierarchy. Hence we have used some annotations to make it as the root.
@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
One Table Per Class Hierarchy
Example-
package com.chetu.training;
import java.util.Date;
import javax.persistence.*;
@Entity
@Table(name="PERSON")
@DiscriminatorValue("E")
public class Employee extends Person {
@Column(name="joining_date")
private Date joiningDate;
@Column(name="department_name")
private String departmentName;
// Constructors and Getter/Setter methods,
}
One Table Per Class Hierarchy
Example:
package com.chetu.training;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Person person = new Person("Steve", "Balmer");
session.save(person);
Employee employee = new Employee("James", "Gosling", "Marketing", new Date());
session.save(employee);
session.getTransaction().commit();
session.close();
}
}
One Table Per Concrete Class
Suppose we have a class Person with subclasses Employee and Owner. Following the class diagram and relationship of these
classes.
In One Table per Concrete class scheme, each concrete class is mapped as normal persistent class. Thus we have 3 tables;
PERSON, EMPLOYEE and OWNER to persist the class data. In this scheme, the mapping of the subclass repeats the properties
of the parent class.
Following are the advantages and disadvantages of One Table per Subclass scheme.
Advantages
This is the easiest method of Inheritance mapping to implement.
Disadvantages
Data thats belongs to a parent class is scattered across a number of subclass tables, which represents concrete classes.
This hierarchy is not recommended for most cases.
Changes to a parent class is reflected to large number of tables.
One Table Per Concrete Class
Example:
Package com.chetu.training;
import javax.persistence.*;
@Entity
@Table(name = "PERSON")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person {
@Id
@Column(name = "PERSON_ID")
private Long personId;
@Column(name = "FIRSTNAME")
private String firstname;
@Column(name = "LASTNAME")
private String lastname;
public Person() {
}
public Person(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
// Getter and Setter methods,
}
One Table Per Concrete Class
@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.
@InheritanceType – Defines inheritance strategy options. TABLE_PER_CLASS is a strategy to map
table per concrete class.
One Table Per Concrete Class
Example:
package com.chetu.training;
import java.util.Date;
import javax.persistence.*;
@Entity
@Table(name="EMPLOYEE")
@AttributeOverrides({ @AttributeOverride(name="firstname", column=@Column(name="FIRSTNAME")), @AttributeOverride(name="lastname",
column=@Column(name="LASTNAME"))
})
public class Employee extends Person {
@Column(name="joining_date")
private Date joiningDate;
@Column(name="department_name")
private String departmentName;
public Employee() {
}
public Employee(String firstname, String lastname, String departmentName, Date joiningDate) {
super(firstname, lastname);
this.departmentName = departmentName;
this.joiningDate = joiningDate;
}
// Getter and Setter methods,
}
One Table Per Concrete Class
Example:
package com.chetu.training;
import javax.persistence.*;
@Entity
@Table(name="OWNER")
@AttributeOverrides({
@AttributeOverride(name="firstname", column=@Column(name="FIRSTNAME")),
@AttributeOverride(name="lastname", column=@Column(name="LASTNAME"))
})
public class Owner extends Person {
@Column(name="stocks")
private Long stocks;
@Column(name="partnership_stake")
private Long partnershipStake;
public Owner() {
}
public Owner(String firstname, String lastname, Long stocks, Long partnershipStake) {
super(firstname, lastname);
this.stocks = stocks;
this.partnershipStake = partnershipStake;
}
// Getter and Setter methods,
}
One Table Per Concrete Class
Both Employee and Owner classes are child of Person class. Thus while specifying the mappings, we used @AttributeOverrides
to map them.
@AttributeOverrides – This annotation is used to override mappings of multiple properties or fields.
@AttributeOverride – The AttributeOverride annotation is used to override the mapping of a Basic (whether explicit or
default) property or field or Id property or field.
The AttributeOverride annotation may be applied to an entity that extends a mapped superclass or to an embedded field or
property to override a basic mapping defined by the mapped superclass or embeddable class. If the AttributeOverride
annotation is not specified, the column is mapped the same as in the original mapping.
Thus in over case, firstname and lastname are defined in parent class Person and mapped in child class Employee and Owner
using @AttributeOverrides annotation.
This strategy supports one-to-many associations provided that they are bidirectional. This strategy does not support the
IDENTITY generator strategy: the id has to be shared across several tables. Consequently, when using this strategy, you should
not use AUTO nor IDENTITY. Note that in below Main class we specified the primary key explicitly.
One Table Per Concrete Class
Example: package com.chetu.training;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Person person = new Person("Steve", "Balmer");
person.setPersonId(1L);
session.save(person);
Employee employee = new Employee("James", "Gosling", "Marketing", new Date());
employee.setPersonId(2L);
session.save(employee);
Owner owner = new Owner("Bill", "Gates", 300L, 20L);
owner.setPersonId(3L);
session.save(owner);
session.getTransaction().commit();
session.close();
}
}
One Table Per Subclass
Suppose we have a class Person with subclass Employee and Owner. Following the class diagram and relationship of these
classes.
In One Table per Subclass scheme, each class persist the data in its own separate table. Thus we have 3 tables; PERSON,
EMPLOYEE and OWNER to persist the class data. Note that a foreign key relationship exists between the subclass tables and
super class table. Thus the common data is stored in PERSON table and subclass specific fields are stored in EMPLOYEE and
OWNER tables.
Following are the advantages and disadvantages of One Table per Subclass scheme.
Advantage
Using this hierarchy, does not require complex changes to the database schema when a single parent class is modified.
It works well with shallow hierarchy.
Disadvantage
As the hierarchy grows, it may result in poor performance.
The number of joins required to construct a subclass also grows.
One Table Per Subclass
Example:
package com.chetu.training;
import javax.persistence.*;
@Entity
@Table(name = "PERSON")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
@Column(name = "PERSON_ID")
private Long personId;
@Column(name = "FIRSTNAME")
private String firstname;
@Column(name = "LASTNAME")
private String lastname;
public Person() {
}
public Person(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
// Getter and Setter methods,
}
One Table Per Subclass
The Person class is the root of hierarchy. Hence we have used some annotations to make it as the root.
@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.
@InheritanceType – Defines inheritance strategy options. JOINED is a strategy in which fields that are specific
to a subclass are mapped to a separate table than the fields that are common to the parent class, and a join is
performed to instantiate the subclass. Thus fields of Employee (joining_date, department) and Owner (stocks
etc) are mapped to their respective tables.
One Table Per Subclass
Example
package com.chetu.training
import java.util.Date;
import javax.persistence.*;
@Entity
@Table(name="EMPLOYEE")
@PrimaryKeyJoinColumn(name="PERSON_ID")
public class Employee extends Person {
@Column(name="joining_date")
private Date joiningDate;
@Column(name="department_name")
private String departmentName;
public Employee() {
}
public Employee(String firstname, String lastname, String departmentName, Date joiningDate) {
super(firstname, lastname);
this.departmentName = departmentName;
this.joiningDate = joiningDate;
}
// Getter and Setter methods,
}
One Table Per Subclass
Example
Package com.chetu.training;
import javax.persistence.*;
@Entity
@Table(name="OWNER")
@PrimaryKeyJoinColumn(name="PERSON_ID")
public class Owner extends Person {
@Column(name="stocks")
private Long stocks;
@Column(name="partnership_stake")
private Long partnershipStake;
public Owner() {
}
public Owner(String firstname, String lastname, Long stocks, Long partnershipStake) {
super(firstname, lastname);
this.stocks = stocks;
this.partnershipStake = partnershipStake;
}
// Getter and Setter methods,
}
One Table Per Subclass
Both Employee and Owner classes are child of Person class. Thus while specifying the mappings, we used
@PrimaryKeyJoinColumn to map it to parent table.
@PrimaryKeyJoinColumn – This annotation specifies a primary key column that is used as a foreign key to join
to another table.
It is used to join the primary table of an entity subclass in the JOINED mapping strategy to the primary table of
its superclass; it is used within a SecondaryTable annotation to join a secondary table to a primary table; and it
may be used in a OneToOne mapping in which the primary key of the referencing entity is used as a foreign key
to the referenced entity.
If no PrimaryKeyJoinColumn annotation is specified for a subclass in the JOINED mapping strategy, the foreign
key columns are assumed to have the same names as the primary key columns of the primary table of the
superclass.
One Table Per Subclass
Example:
Package com.chetu.training;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Person person = new Person("Steve", "Balmer");
session.save(person);
Employee employee = new Employee("James", "Gosling", "Marketing", new Date());
session.save(employee);
Owner owner = new Owner("Bill", "Gates", 300L, 20L);
session.save(owner);
session.getTransaction().commit();
session.close();
}
}
Hibernate Mappings
Hibernate supports the following Mappings as the relational database supports:
1.One to One
2.Many to One
3.Many to Many.
One to One mapping
Example: package com.chetu.training;
import java.sql.Date;
import javax.persistence.*;
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@GeneratedValue
@Column(name="employee_id")
private Long employeeId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="birth_date")
private Date birthDate;
One to One mapping
@Column(name="cell_phone")
private String cellphone;
@OneToOne(mappedBy="employee", cascade=CascadeType.ALL)
private EmployeeDetail employeeDetail;
public Employee() {
}
public Employee(String firstname, String lastname, Date birthdate, String phone) {
this.firstname = firstname;
this.lastname = lastname;
this.birthDate = birthdate;
this.cellphone = phone;
}
// Getter and Setter methods
}
One to One mapping
Example:
package com.chetu.training;
import javax.persistence.*;
import org.hibernate.annotations.*
@Entity
@Table(name="EMPLOYEEDETAIL")
public class EmployeeDetail {
@Id
@Column(name="employee_id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="employee"))
private Long employeeId;
@Column(name="street")
private String street;
@Column(name="city")
private String city;
@Column(name="state")
private String state;
@Column(name="country")
private String country;
One to One mapping
@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;
public EmployeeDetail() {
}
public EmployeeDetail(String street, String city, String state, String country) {
this.street = street;
this.city = city;
this.state = state;
this.country = country;
}
// Getter and Setter methods
}
One to One mapping
Example:
package com.chetu.training;
import java.sql.Date;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
EmployeeDetail employeeDetail = new EmployeeDetail("10th Street", "LA", "San Francisco", "U.S.");
Employee employee = new Employee("Nina", "Mayers", new Date(121212),"114-857-965");
employee.setEmployeeDetail(employeeDetail);
employeeDetail.setEmployee(employee);
session.save(employee);
List<Employee> employees = session.createQuery("from Employee").list();
for (Employee employee1 : employees) {
System.out.println(employee1.getFirstname() + " , "+ employee1.getLastname() + ", "+ employee1.getEmployeeDetail().getState());
}
session.getTransaction().commit();
session.close();
}}
One to Many or Many to One mapping
Example:
Package com.chetu.training;
import java.sql.Date;
import javax.persistence.*;
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@GeneratedValue
@Column(name="employee_id")
private Long employeeId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="birth_date")
private Date birthDate;
@Column(name="cell_phone")
private String cellphone;
One to Many or Many to One mapping
@ManyToOne
@JoinColumn(name="department_id")
private Department department;
public Employee() {
}
public Employee(String firstname, String lastname, String phone) {
this.firstname = firstname;
this.lastname = lastname;
this.birthDate = new Date(System.currentTimeMillis());
this.cellphone = phone;
}
// Getter and Setter methods
}
One to Many or Many to One mapping
Example:
@ManyToOne annotation defines a single-valued association to another entity class that has many-to-one multiplicity. It is not normally necessary to specify the target
target entity explicitly since it can usually be inferred from the type of the object being referenced.
@JoinColumn is used to specify a mapped column for joining an entity association.
Package com.chetu.training;
import java.util.Set;
import javax.persistence.*;
@Entity
@Table(name="DEPARTMENT")
public class Department {
@Id
@GeneratedValue
@Column(name="DEPARTMENT_ID")
private Long departmentId;
@Column(name="DEPT_NAME")
private String departmentName;
@OneToMany(mappedBy="department")
private Set<Employee> employees;
// Getter and Setter methods
}
One to Many or Many to One mapping
@OneToMany annotation defines a many-valued association with one-to-many multiplicity.
If the collection is defined using generics to specify the element type, the associated target entity type need
be specified; otherwise the target entity class must be specified.
The association may be bidirectional. In a bidirectional relationship, one of the sides (and only one) has to be
the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible
for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the
on the owner side. In our case, this is passport. As you can see, you don’t have to (must not) declare the join
column since it has already been declared on the owners side.
One to Many or Many to One mapping
Example:
Package com.chetu.training;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Department department = new Department();
department.setDepartmentName("Sales");
session.save(department);
Employee emp1 = new Employee("Nina", "Mayers", "111");
Employee emp2 = new Employee("Tony", "Almeida", "222");
emp1.setDepartment(department);
emp2.setDepartment(department);
session.save(emp1);
session.save(emp2);
session.getTransaction().commit();
session.close();
}
}
Many to Many mapping
Example:
package net.viralpatel.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@Column(name="EMPLOYEE_ID")
@GeneratedValue
private Long employeeId;
@Column(name="FIRSTNAME")
private String firstname;
@Column(name="LASTNAME")
private String lastname;
Many to Many mapping
@ManyToMany(cascade = {CascadeType.ALL})
@JoinTable(name="EMPLOYEE_MEETING",
joinColumns={@JoinColumn(name="EMPLOYEE_ID")},
inverseJoinColumns={@JoinColumn(name="MEETING_ID")})
private Set<Meeting> meetings = new HashSet<Meeting>();
public Employee() {
}
public Employee(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
// Getter and Setter methods
}
Many to Many mapping
Package com.chetu.training;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
@Entity
@Table(name="MEETING")
public class Meeting {
@Id
@Column(name="MEETING_ID")
@GeneratedValue
private Long meetingId;
@Column(name="SUBJECT")
private String subject;
@Column(name="MEETING_DATE")
private Date meetingDate;
}
Many to Many mapping
@ManyToMany(mappedBy="meetings")
private Set<Employee> employees = new HashSet<Employee>();
public Meeting(String subject) {
this.subject = subject;
this.meetingDate = new Date();
}
// Getter and Setter methods
}
Many to Many mapping
Let us understand the annotations we used here to map Many to many relationship.
@ManyToMany – Is used to create many-to-many relationship between Employee and Meeting entities. If the Collection is defined using
generics to specify the element type, the associated target entity class does not need to be specified; otherwise it must be specified. Every
many-to-many association has two sides, the owning side and the non-owning, or inverse, side. The join table is specified on the owning side. If
the association is bidirectional, either side may be designated as the owning side.
Note that in above entity classes, Employee is defined as relationship owner as @JoinColumn is define in Employee class and mappedBy is
specified in Meeting class.
@JoinTable – Is used to define the join table (link table) for many-to-many relationship. It is specified on the owning side of a many-to-many
association, or in a unidirectional one-to-many association. In this case the join table is EMPLOYEE_MEETING.
If the JoinTable annotation is missing, the default values of the annotation elements apply. The name of the join table is assumed to be the
table names of the associated primary tables concatenated together (owning side first) using an underscore.
@JoinColumn – Is used to define the join column (linking column) in both main tables.
Many to Many mapping
Note: that we have used SET to map meetings with employee and vice versa. A <set> is similar to except that it
it can only store unique objects. That means no duplicate elements can be contained in a set. When you add the
same element to a set for second time, it will replace the old one. A set is unordered by default but we can ask it
to be sorted. The corresponding type of a <set> in Java is java.util.Set.
Many to Many mapping
Example:
package com.chetu.training;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Meeting meeting1 = new Meeting("Quaterly Sales meeting");
Meeting meeting2 = new Meeting("Weekly Status meeting");
Employee employee1 = new Employee("Sergey", "Brin");
Employee employee2 = new Employee("Larry", "Page");
employee1.getMeetings().add(meeting1);
employee1.getMeetings().add(meeting2);
employee2.getMeetings().add(meeting1);
session.save(employee1);
session.save(employee2);
session.getTransaction().commit();
session.close();
}
}

Hibernate inheritance and relational mappings with examples

  • 1.
    Hibernate INHERITANCE AND RELATIONALMAPPINGS - BY GAURAV KUMAR
  • 2.
    Inheritance  Java isan object oriented language. It is possible to implement Inheritance in Java. Inheritance is one of the most visible facets of Object-relational mismatch. Object oriented systems can model both “is a” and “has a” relationship. Relational model supports only “has a” relationship between two entities. Hibernate can help you map such Objects with relational tables. But you need to choose certain mapping strategy based on your needs.
  • 3.
    One Table PerClass Hierarchy Suppose we have a class Person with subclass Employee. The properties of each class are: • class Person - firstname - lastname • class Employee - joining_date - department_name In One Table per Class Hierarchy scheme, we store all the class hierarchy in a single SQL table. A discriminator is a key to uniquely identify the base type of the class hierarchy. Following are the advantages and disadvantages of One Table per Class Hierarchy scheme. Advantage This hierarchy offers the best performance even for in the deep hierarchy since single select may suffice. Disadvantage Changes to members of the hierarchy require column to be altered, added or removed from the table.
  • 4.
    One Table PerClass Hierarchy Example:- package com.chaetu.training; import javax.persistence.*; @Entity @Table(name = "PERSON") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="discriminator", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue(value="P") public class Person { @Id @GeneratedValue @Column(name = "PERSON_ID") private Long personId; @Column(name = "FIRSTNAME") private String firstname; @Column(name = "LASTNAME") private String lastname; // Constructors and Getter/Setter methods, }
  • 5.
    One Table PerClass Hierarchy The Person class is the root of hierarchy. Hence we have used some annotations to make it as the root. @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
  • 6.
    One Table PerClass Hierarchy Example- package com.chetu.training; import java.util.Date; import javax.persistence.*; @Entity @Table(name="PERSON") @DiscriminatorValue("E") public class Employee extends Person { @Column(name="joining_date") private Date joiningDate; @Column(name="department_name") private String departmentName; // Constructors and Getter/Setter methods, }
  • 7.
    One Table PerClass Hierarchy Example: package com.chetu.training; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Person person = new Person("Steve", "Balmer"); session.save(person); Employee employee = new Employee("James", "Gosling", "Marketing", new Date()); session.save(employee); session.getTransaction().commit(); session.close(); } }
  • 8.
    One Table PerConcrete Class Suppose we have a class Person with subclasses Employee and Owner. Following the class diagram and relationship of these classes. In One Table per Concrete class scheme, each concrete class is mapped as normal persistent class. Thus we have 3 tables; PERSON, EMPLOYEE and OWNER to persist the class data. In this scheme, the mapping of the subclass repeats the properties of the parent class. Following are the advantages and disadvantages of One Table per Subclass scheme. Advantages This is the easiest method of Inheritance mapping to implement. Disadvantages Data thats belongs to a parent class is scattered across a number of subclass tables, which represents concrete classes. This hierarchy is not recommended for most cases. Changes to a parent class is reflected to large number of tables.
  • 9.
    One Table PerConcrete Class Example: Package com.chetu.training; import javax.persistence.*; @Entity @Table(name = "PERSON") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Person { @Id @Column(name = "PERSON_ID") private Long personId; @Column(name = "FIRSTNAME") private String firstname; @Column(name = "LASTNAME") private String lastname; public Person() { } public Person(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } // Getter and Setter methods, }
  • 10.
    One Table PerConcrete Class @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. @InheritanceType – Defines inheritance strategy options. TABLE_PER_CLASS is a strategy to map table per concrete class.
  • 11.
    One Table PerConcrete Class Example: package com.chetu.training; import java.util.Date; import javax.persistence.*; @Entity @Table(name="EMPLOYEE") @AttributeOverrides({ @AttributeOverride(name="firstname", column=@Column(name="FIRSTNAME")), @AttributeOverride(name="lastname", column=@Column(name="LASTNAME")) }) public class Employee extends Person { @Column(name="joining_date") private Date joiningDate; @Column(name="department_name") private String departmentName; public Employee() { } public Employee(String firstname, String lastname, String departmentName, Date joiningDate) { super(firstname, lastname); this.departmentName = departmentName; this.joiningDate = joiningDate; } // Getter and Setter methods, }
  • 12.
    One Table PerConcrete Class Example: package com.chetu.training; import javax.persistence.*; @Entity @Table(name="OWNER") @AttributeOverrides({ @AttributeOverride(name="firstname", column=@Column(name="FIRSTNAME")), @AttributeOverride(name="lastname", column=@Column(name="LASTNAME")) }) public class Owner extends Person { @Column(name="stocks") private Long stocks; @Column(name="partnership_stake") private Long partnershipStake; public Owner() { } public Owner(String firstname, String lastname, Long stocks, Long partnershipStake) { super(firstname, lastname); this.stocks = stocks; this.partnershipStake = partnershipStake; } // Getter and Setter methods, }
  • 13.
    One Table PerConcrete Class Both Employee and Owner classes are child of Person class. Thus while specifying the mappings, we used @AttributeOverrides to map them. @AttributeOverrides – This annotation is used to override mappings of multiple properties or fields. @AttributeOverride – The AttributeOverride annotation is used to override the mapping of a Basic (whether explicit or default) property or field or Id property or field. The AttributeOverride annotation may be applied to an entity that extends a mapped superclass or to an embedded field or property to override a basic mapping defined by the mapped superclass or embeddable class. If the AttributeOverride annotation is not specified, the column is mapped the same as in the original mapping. Thus in over case, firstname and lastname are defined in parent class Person and mapped in child class Employee and Owner using @AttributeOverrides annotation. This strategy supports one-to-many associations provided that they are bidirectional. This strategy does not support the IDENTITY generator strategy: the id has to be shared across several tables. Consequently, when using this strategy, you should not use AUTO nor IDENTITY. Note that in below Main class we specified the primary key explicitly.
  • 14.
    One Table PerConcrete Class Example: package com.chetu.training; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Person person = new Person("Steve", "Balmer"); person.setPersonId(1L); session.save(person); Employee employee = new Employee("James", "Gosling", "Marketing", new Date()); employee.setPersonId(2L); session.save(employee); Owner owner = new Owner("Bill", "Gates", 300L, 20L); owner.setPersonId(3L); session.save(owner); session.getTransaction().commit(); session.close(); } }
  • 15.
    One Table PerSubclass Suppose we have a class Person with subclass Employee and Owner. Following the class diagram and relationship of these classes. In One Table per Subclass scheme, each class persist the data in its own separate table. Thus we have 3 tables; PERSON, EMPLOYEE and OWNER to persist the class data. Note that a foreign key relationship exists between the subclass tables and super class table. Thus the common data is stored in PERSON table and subclass specific fields are stored in EMPLOYEE and OWNER tables. Following are the advantages and disadvantages of One Table per Subclass scheme. Advantage Using this hierarchy, does not require complex changes to the database schema when a single parent class is modified. It works well with shallow hierarchy. Disadvantage As the hierarchy grows, it may result in poor performance. The number of joins required to construct a subclass also grows.
  • 16.
    One Table PerSubclass Example: package com.chetu.training; import javax.persistence.*; @Entity @Table(name = "PERSON") @Inheritance(strategy=InheritanceType.JOINED) public class Person { @Id @GeneratedValue @Column(name = "PERSON_ID") private Long personId; @Column(name = "FIRSTNAME") private String firstname; @Column(name = "LASTNAME") private String lastname; public Person() { } public Person(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } // Getter and Setter methods, }
  • 17.
    One Table PerSubclass The Person class is the root of hierarchy. Hence we have used some annotations to make it as the root. @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. @InheritanceType – Defines inheritance strategy options. JOINED is a strategy in which fields that are specific to a subclass are mapped to a separate table than the fields that are common to the parent class, and a join is performed to instantiate the subclass. Thus fields of Employee (joining_date, department) and Owner (stocks etc) are mapped to their respective tables.
  • 18.
    One Table PerSubclass Example package com.chetu.training import java.util.Date; import javax.persistence.*; @Entity @Table(name="EMPLOYEE") @PrimaryKeyJoinColumn(name="PERSON_ID") public class Employee extends Person { @Column(name="joining_date") private Date joiningDate; @Column(name="department_name") private String departmentName; public Employee() { } public Employee(String firstname, String lastname, String departmentName, Date joiningDate) { super(firstname, lastname); this.departmentName = departmentName; this.joiningDate = joiningDate; } // Getter and Setter methods, }
  • 19.
    One Table PerSubclass Example Package com.chetu.training; import javax.persistence.*; @Entity @Table(name="OWNER") @PrimaryKeyJoinColumn(name="PERSON_ID") public class Owner extends Person { @Column(name="stocks") private Long stocks; @Column(name="partnership_stake") private Long partnershipStake; public Owner() { } public Owner(String firstname, String lastname, Long stocks, Long partnershipStake) { super(firstname, lastname); this.stocks = stocks; this.partnershipStake = partnershipStake; } // Getter and Setter methods, }
  • 20.
    One Table PerSubclass Both Employee and Owner classes are child of Person class. Thus while specifying the mappings, we used @PrimaryKeyJoinColumn to map it to parent table. @PrimaryKeyJoinColumn – This annotation specifies a primary key column that is used as a foreign key to join to another table. It is used to join the primary table of an entity subclass in the JOINED mapping strategy to the primary table of its superclass; it is used within a SecondaryTable annotation to join a secondary table to a primary table; and it may be used in a OneToOne mapping in which the primary key of the referencing entity is used as a foreign key to the referenced entity. If no PrimaryKeyJoinColumn annotation is specified for a subclass in the JOINED mapping strategy, the foreign key columns are assumed to have the same names as the primary key columns of the primary table of the superclass.
  • 21.
    One Table PerSubclass Example: Package com.chetu.training; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Person person = new Person("Steve", "Balmer"); session.save(person); Employee employee = new Employee("James", "Gosling", "Marketing", new Date()); session.save(employee); Owner owner = new Owner("Bill", "Gates", 300L, 20L); session.save(owner); session.getTransaction().commit(); session.close(); } }
  • 22.
    Hibernate Mappings Hibernate supportsthe following Mappings as the relational database supports: 1.One to One 2.Many to One 3.Many to Many.
  • 23.
    One to Onemapping Example: package com.chetu.training; import java.sql.Date; import javax.persistence.*; @Entity @Table(name="EMPLOYEE") public class Employee { @Id @GeneratedValue @Column(name="employee_id") private Long employeeId; @Column(name="firstname") private String firstname; @Column(name="lastname") private String lastname; @Column(name="birth_date") private Date birthDate;
  • 24.
    One to Onemapping @Column(name="cell_phone") private String cellphone; @OneToOne(mappedBy="employee", cascade=CascadeType.ALL) private EmployeeDetail employeeDetail; public Employee() { } public Employee(String firstname, String lastname, Date birthdate, String phone) { this.firstname = firstname; this.lastname = lastname; this.birthDate = birthdate; this.cellphone = phone; } // Getter and Setter methods }
  • 25.
    One to Onemapping Example: package com.chetu.training; import javax.persistence.*; import org.hibernate.annotations.* @Entity @Table(name="EMPLOYEEDETAIL") public class EmployeeDetail { @Id @Column(name="employee_id", unique=true, nullable=false) @GeneratedValue(generator="gen") @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="employee")) private Long employeeId; @Column(name="street") private String street; @Column(name="city") private String city; @Column(name="state") private String state; @Column(name="country") private String country;
  • 26.
    One to Onemapping @OneToOne @PrimaryKeyJoinColumn private Employee employee; public EmployeeDetail() { } public EmployeeDetail(String street, String city, String state, String country) { this.street = street; this.city = city; this.state = state; this.country = country; } // Getter and Setter methods }
  • 27.
    One to Onemapping Example: package com.chetu.training; import java.sql.Date; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); EmployeeDetail employeeDetail = new EmployeeDetail("10th Street", "LA", "San Francisco", "U.S."); Employee employee = new Employee("Nina", "Mayers", new Date(121212),"114-857-965"); employee.setEmployeeDetail(employeeDetail); employeeDetail.setEmployee(employee); session.save(employee); List<Employee> employees = session.createQuery("from Employee").list(); for (Employee employee1 : employees) { System.out.println(employee1.getFirstname() + " , "+ employee1.getLastname() + ", "+ employee1.getEmployeeDetail().getState()); } session.getTransaction().commit(); session.close(); }}
  • 28.
    One to Manyor Many to One mapping Example: Package com.chetu.training; import java.sql.Date; import javax.persistence.*; @Entity @Table(name="EMPLOYEE") public class Employee { @Id @GeneratedValue @Column(name="employee_id") private Long employeeId; @Column(name="firstname") private String firstname; @Column(name="lastname") private String lastname; @Column(name="birth_date") private Date birthDate; @Column(name="cell_phone") private String cellphone;
  • 29.
    One to Manyor Many to One mapping @ManyToOne @JoinColumn(name="department_id") private Department department; public Employee() { } public Employee(String firstname, String lastname, String phone) { this.firstname = firstname; this.lastname = lastname; this.birthDate = new Date(System.currentTimeMillis()); this.cellphone = phone; } // Getter and Setter methods }
  • 30.
    One to Manyor Many to One mapping Example: @ManyToOne annotation defines a single-valued association to another entity class that has many-to-one multiplicity. It is not normally necessary to specify the target target entity explicitly since it can usually be inferred from the type of the object being referenced. @JoinColumn is used to specify a mapped column for joining an entity association. Package com.chetu.training; import java.util.Set; import javax.persistence.*; @Entity @Table(name="DEPARTMENT") public class Department { @Id @GeneratedValue @Column(name="DEPARTMENT_ID") private Long departmentId; @Column(name="DEPT_NAME") private String departmentName; @OneToMany(mappedBy="department") private Set<Employee> employees; // Getter and Setter methods }
  • 31.
    One to Manyor Many to One mapping @OneToMany annotation defines a many-valued association with one-to-many multiplicity. If the collection is defined using generics to specify the element type, the associated target entity type need be specified; otherwise the target entity class must be specified. The association may be bidirectional. In a bidirectional relationship, one of the sides (and only one) has to be the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the on the owner side. In our case, this is passport. As you can see, you don’t have to (must not) declare the join column since it has already been declared on the owners side.
  • 32.
    One to Manyor Many to One mapping Example: Package com.chetu.training; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Department department = new Department(); department.setDepartmentName("Sales"); session.save(department); Employee emp1 = new Employee("Nina", "Mayers", "111"); Employee emp2 = new Employee("Tony", "Almeida", "222"); emp1.setDepartment(department); emp2.setDepartment(department); session.save(emp1); session.save(emp2); session.getTransaction().commit(); session.close(); } }
  • 33.
    Many to Manymapping Example: package net.viralpatel.hibernate; import java.util.HashSet; import java.util.Set; import javax.persistence.*; @Entity @Table(name="EMPLOYEE") public class Employee { @Id @Column(name="EMPLOYEE_ID") @GeneratedValue private Long employeeId; @Column(name="FIRSTNAME") private String firstname; @Column(name="LASTNAME") private String lastname;
  • 34.
    Many to Manymapping @ManyToMany(cascade = {CascadeType.ALL}) @JoinTable(name="EMPLOYEE_MEETING", joinColumns={@JoinColumn(name="EMPLOYEE_ID")}, inverseJoinColumns={@JoinColumn(name="MEETING_ID")}) private Set<Meeting> meetings = new HashSet<Meeting>(); public Employee() { } public Employee(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } // Getter and Setter methods }
  • 35.
    Many to Manymapping Package com.chetu.training; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.persistence.*; @Entity @Table(name="MEETING") public class Meeting { @Id @Column(name="MEETING_ID") @GeneratedValue private Long meetingId; @Column(name="SUBJECT") private String subject; @Column(name="MEETING_DATE") private Date meetingDate; }
  • 36.
    Many to Manymapping @ManyToMany(mappedBy="meetings") private Set<Employee> employees = new HashSet<Employee>(); public Meeting(String subject) { this.subject = subject; this.meetingDate = new Date(); } // Getter and Setter methods }
  • 37.
    Many to Manymapping Let us understand the annotations we used here to map Many to many relationship. @ManyToMany – Is used to create many-to-many relationship between Employee and Meeting entities. If the Collection is defined using generics to specify the element type, the associated target entity class does not need to be specified; otherwise it must be specified. Every many-to-many association has two sides, the owning side and the non-owning, or inverse, side. The join table is specified on the owning side. If the association is bidirectional, either side may be designated as the owning side. Note that in above entity classes, Employee is defined as relationship owner as @JoinColumn is define in Employee class and mappedBy is specified in Meeting class. @JoinTable – Is used to define the join table (link table) for many-to-many relationship. It is specified on the owning side of a many-to-many association, or in a unidirectional one-to-many association. In this case the join table is EMPLOYEE_MEETING. If the JoinTable annotation is missing, the default values of the annotation elements apply. The name of the join table is assumed to be the table names of the associated primary tables concatenated together (owning side first) using an underscore. @JoinColumn – Is used to define the join column (linking column) in both main tables.
  • 38.
    Many to Manymapping Note: that we have used SET to map meetings with employee and vice versa. A <set> is similar to except that it it can only store unique objects. That means no duplicate elements can be contained in a set. When you add the same element to a set for second time, it will replace the old one. A set is unordered by default but we can ask it to be sorted. The corresponding type of a <set> in Java is java.util.Set.
  • 39.
    Many to Manymapping Example: package com.chetu.training; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Meeting meeting1 = new Meeting("Quaterly Sales meeting"); Meeting meeting2 = new Meeting("Weekly Status meeting"); Employee employee1 = new Employee("Sergey", "Brin"); Employee employee2 = new Employee("Larry", "Page"); employee1.getMeetings().add(meeting1); employee1.getMeetings().add(meeting2); employee2.getMeetings().add(meeting1); session.save(employee1); session.save(employee2); session.getTransaction().commit(); session.close(); } }