Engineering Full Stack Apps with Java and JavaScript
When mapping two entities, we annotate both classes as @Entity and the mapping type is specified as @OneToOne, @OneToMany, @ManyToOne or @ManyToMany over the declaration of one entity class in the other entity class. In One-To-One mapping, we refer to one entity from another and mark the reference variable as @OneToOne.
We will see an example mapping of two entity classes – student class and course class; and do a one to one mapping from course to student. We will assume that there is a one-to-one mapping between a Course and Student – each course can be taken by only one student. If you are not following the tutorials in order, refer to the article http://javajee.com/your-first-hibernate-program for the basic setup including hibernate configuration file. You should replace the user class in the configuration file with both course and student classes as:
<!-- Names the annotated entity class -->
<mapping class="com.javajee.hiberex.dto.Student"/>
<mapping class="com.javajee.hiberex.dto.Course"/>
Else you will get org.hibernate.MappingException: Unknown entity:…
The student class will be a normal entity class similar to our earlier user class (except for name).
Our Student class will look as below:
package com.javajee.hiberex.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Student {
@Id
private int studId;
private String studName;
//Getters and setters not shown here; create them manually or generate in eclipse.
}
The Course class is similar to the Student class, but will have a reference to the student class annotated as @OneToOne:
package com.javajee.hiberex.dto;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Course {
@Id @GeneratedValue
private int courseId;
private String courseName;
@OneToOne
private Student stud;
//Getters and setters not shown here; create them manually or generate in eclipse.
}
We also need a test class to test. The test class will look as below:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.javajee.hiberex.dto.Course;
import com.javajee.hiberex.dto.Student;
public class CourseTest {
public static void main(String[] args) {
Student stud = new Student();
stud.setStudName("Stud1");
Course course = new Course();
course.setCourseName("C1");
course.setStud(stud);
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(stud);
session.save(course);
session.getTransaction().commit();
}
}
If you run CourseTest.java (after you generate all getters and setters for course and student), you will see the below queries in console:
Hibernate: insert into Student (studName) values (?)
Hibernate: insert into Course (courseName, stud_studId) values (?, ?)
Here, Student class is saved with an auto generated id and Course class has an extra column that has the corresponding student id.
Now make a small modification to the test class. Change the order of save of student and course as:
session.save(course);
session.save(stud);
If you run CourseTest.java, you will see the below queries in console:
Hibernate: insert into Course (courseName, stud_studId) values (?, ?)
Hibernate: insert into Student (studName) values (?)
Hibernate: update Course set courseName=?, stud_studId=? where courseId=?
When data is inserted to Course table, studId is not known, but after inserting into Student table, the studId is updated in Course table. Here the join column is stud_studId and you can change its name using @JoinColumn() annotation as:
…
@OneToOne
@JoinColumn(name="stud_id")
private Student stud;
…