Hibernate Mapping

Hibernate is a ORM framework which will map our database tables into our POJO classes. By this, we can do the database operations like insert, update, select and etc. When we come to hibernate mapping, we have the below relationships between entities as in RDBS,
  1. OneToOne
  2. OneToMany
  3. ManyToOne
  4. ManyToOne
We can wire the relationships between our entities by these mappings. We can do these mappings in both the ways, unidirectional and bidirectional. But we just concentrate only on unidirectional mapping here.
Example:
Let’s consider we have student database where we have 6 tables named student, student_address, course_details, month_attendance, academic_subject, student_subject.

OneToOne
Each student has one address and each address has one student. So student has one to one relationship with address entity.

OneToMany
We are tracking monthly attendance of every student in month_attendance table. Each student has more than one record in month_attendance. At the same time, one record in month_attendance is associated with only one student. So student has OneToMany relationship with month_attendance.

ManyToOne
Each student has one course, but one course can have more than one student.

ManyToMany
One student can have multiple subjects and one subject can have many students. So this’s a ManyToMany relationship.
Please note down the mapping table student_subject which establishes the many to many relationship between student and subject.
Now let’s see the below code snippets to know how we wire the relationships between these entities.
Code:
Student.java
 @Entity  
@Table(name="student")
public class Student implements Serializable {

@Id
@Column(name="student_id")
@GeneratedValue(strategy= GenerationType.AUTO)
private String studentId;

@Column(name="student_name")
private String studentName;

@Column(name="date_of_birth")
private String dob;

@OneToOne
@JoinColumn(name="student_id")
private Address address;

@ManyToOne
@JoinColumn(name="course_id")
private StudentCourse studentCourse;

@OneToMany(mappedBy = "monthAttendancePK.studentId")
private Set<MonthAttendance> monthAttendances;

@ManyToMany
@JoinTable(name = "student_subject",joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "subject_id"))
private Set<Subject> subjects;

/*
*Other properties and mutators
*/
}

Address.java

 @Entity  
@Table(name="student_address")
public class Address {
@Id
@Column(name="student_id")
private String studentId;

private String location;

private String city;

private String country;

/*
*Other properties and mutators
*/
}

Notice the variables location, city, country. We didn’t specify the column annotation. Because the variable name and database column name both are same here. So no need to specify it explicitly.

StudentCourse.java

 @Entity  
@Table(name="course_details")
public class StudentCourse implements Serializable {

@Id
@Column(name="course_id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private String courseId;

@Column(name="course_name")
private String courseName;

private String department;

@Column(name="class_location")
private String classLocation;

private String hod;

/*
*Other properties and mutators
*/
}

Composite Primary Key:
Creating a entity class for the month_attendance table is quite different from all other entities which we saw above. Because month_attendance has composite primary key means it’s a combination of  two different columns, student_id and month_year. So we declare MonthAttendancePK entity, which holds only the primary key columns, along with MonthAttendance entity which holds all column properties other than the primary keys. We will get a better understanding, when we look at the below code.

MonthAttendancePK.java

 @Embeddable  
public class MonthAttendancePK implements Serializable {

@Column(name="student_id")
private String studentId;

@Column(name="month_year")
private String monthYear;

/*
*Other properties and mutators
*/
}

The below MonthAttendance class will have this MonthAttendancePK and it’s annotated by @EmbeddedId

MonthAttendance.java

 @Entity  
@Table(name="month_attendance")
public class MonthAttendance implements Serializable {

@EmbeddedId
private MonthAttendancePK monthAttendancePK;

@Column(name="percentage")
private String percentage;

@Column(name="medical_leaves")
private String medicalLeaves;

@Column(name="planned_leaves")
private String plannedLeaves;

@Column(name="urgent_leaves")
private String urgentLeaves;

/*
*Other properties and mutators
*/

}

Please take a note that we didn’t use the @Id annotation, when it comes to composite primary key. Let’s have a look at the many to many relationship.

Subject.java

 @Entity  
@Table(name="academic_subject")
public class Subject {

@Id
@Column(name="subject_id")
@GeneratedValue(strategy= GenerationType.AUTO)
private String subjectId;

@Column(name="subject_name")
private String subjectName;

@Column(name="recommended_books")
private String recommendedBooks;

/*
*Other properties and mutators
*/
}

We didn’t have any entity for the table student_subject. Because it’s just a mapping table represents the many to many relationship between student and academic_subject.

SessionFactory:

We can do the database operations through EntityManagerFactory or SessionFactory. EntityManagerFactory is JPA specific API means that it is provided by the Java. Hibernate has the implementation of this API. If we use this EntityManagerFactory, we can easily move between different ORM frameworks. But, In this example, we used hibernate specific SessionFactory. Because hibernate is a more popular and commonly used ORM framework nowadays and it has more features than the JPA specific API. So we don’t need to move to different ORM framework. Now let’s see how we configured the SessionFactory in ApplicationContext file,

   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/usersproduct" />
<property name="username" value="root"/>
<property name="password" value="9may89mysql"/>
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.sample.model.Student</value>
<value>com.sample.model.StudentCourse</value>
<value>com.sample.model.MonthAttendance</value>
<value>com.sample.model.Subject</value>
<value>com.sample.model.Address</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

We used this SessionFactory in the below dao class to fetch all the students and to fetch a student by the given student id along with address, attendance, course, subject details as we configured the relationships.

StudentDaoImpl.java
 @Repository  
public class StudentDaoImpl implements StudentDao{
@Autowired(required = true)
private SessionFactory sessionFactory;
public List<Student> listStudents() {
Session session = this.sessionFactory.openSession();
List<Student> studentList = session.createQuery("from Student").list();
return studentList;
}
public Student getStudentData(String studentId) {
Session session = this.sessionFactory.openSession();
List<Student> studentList = new ArrayList<Student>();
Student student = session.get(Student.class,studentId);
return student;
}
}

Please Click here to download this project from GitHub.

Published