This post is continuation to my last post - hibernate annotations. Here we will be discussing about hibernate one to one mapping in detail with an example. We will take a look into both unidirectional and bidirectional one to one realationship and even discuss about different optional annotations used in one to one mapping such as mappedBy, CascadeType, FetchTye and others.
What is One to One Mapping
One to One relation specifies that an entity(A) is associated to only a single instance of another entity(B). From database perspective, you can assume that if table A has a one to one mapping with table B, then each row of Table B will have a foreign key column which refers to a primary key of Table A.
Let us represent this in a SQL query. Following is the table structure we will be using for this example.
CREATE TABLE EMPLOYEES ( RECORD_ID INT NOT NULL AUTO_INCREMENT, AGE INT, NAME VARCHAR(255), PRIMARY KEY (RECORD_ID) ) ENGINE=InnoDB; CREATE TABLE PHONES ( RECORD_ID INT NOT NULL AUTO_INCREMENT, NAME VARCHAR(255), EMP_ID INT, PRIMARY KEY (RECORD_ID) ) ENGINE=InnoDB; ALTER TABLE phones ADD CONSTRAINT FK_28498m2ap6ybm5xn8tce6iwmh FOREIGN KEY (EMP_ID) REFERENCES EMPLOYEES (RECORD_ID)
From above sql its clear that table PHONES
has a foreign key column - EMP_ID that references to primary key of table EMPLOYEES
and there is one to one mapping in between them meaning one row of table PHONES
is refering to single row of table EMPLOYEES
via foreign key EMP_ID
present in table PHONES
.
Environment Setup
1. JDK 7 2. Hibernate 4 3. Intellij Idea/ eclipse 4. MySql 5. Maven
Project Structure
We have 2 model classes - Employee.java
and Phone.java
that has one to one relationship. We have Application.java
that has a main method which will be used to start the application. Here the hibernate.cfg.xml
file is under hibernate directory.
Maven Dependencies
Following are the maven dependencies required to include in pom.xml to get started.
pom.xml<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.11.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.18.0-GA</version> </dependency> </dependencies>
Other Interesting Posts Spring Hibernate Integration Example with JavaConfig Object Relational Mapping in Java Hibernate Different Annotations Example Hibernate One to Many Relationship Example Hibernate Many to Many Relationship Example Hibernate Inheritance Example
Defining hibernate.cfg.xml
<hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="show_sql">false</property> <mapping class="com.devglan.model.Employee"/> <mapping class="com.devglan.model.Phone"/> </session-factory> </hibernate-configuration>
Defining hibernate Entities for One to One Mapping
From above sql queries we confirmed that table EMPLOYEES
and PHONES
have one to one mapping. Now let us define it in hibernate first and then we will discuss different about different annotations involved.
package com.devglan.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "EMPLOYEES") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "RECORD_ID") private Integer id; @Column(name = "NAME") private String name; @Column(name="AGE") private Integer age; @OneToOne(mappedBy = "emp") private Phone phone; public Employee() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Phone getPhone() { return phone; } public void setPhone(Phone phone) { this.phone = phone; } }
You can see the annotation @OneToOne that adds metadata as Employee class has one to one mapping with Phone.java as thi annotation is defined above the Phone class variable declaration. We ill be discussing about other attributes in coming section. Now let us define Phone.java
package com.devglan.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name = "PHONES") public class Phone { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "RECORD_ID") privateInteger id; @Column(name = "NAME") private String no; @OneToOne @JoinColumn(name = "EMP_ID") private Employee emp; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public Employee getEmp() { return emp; } public void setEmp(Employee emp) { this.emp = emp; } }
In Phone.java you can see @JoinColumn annotation that adds metadata about foeign key column. Above entity configurations are for unidirectional mapping relations as we are using mappedBy attribute.
Optional Attributes used in One TO One Mapping
Apart from annotations used in the entity class, there are other optional annotations that we can use during hibernate one to one mapping.
CascadeType - It defines operaions that must be cascaded. By default, no operation is cascaded. For different types of cascading follow Hibernate Docs
mappedBy - It defines the field which owns the relationship. This element is specified on the now owning side of the association. This is only required when relationship is unidirectional. Owning side is the entity having foreign column.
Fetch - It defines whether mapped entity should be lazily or eagerly initialised.
Example Operations in One to One Mapping
Now let us see how to create entries of mapped entities in database using hibernate.
Application.javapackage com.devglan.model; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; public class Application { public static void main(String[] args) { createEmployee(); } public static SessionFactory getSessionFactory() { Configuration configuration = new Configuration().configure(); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() .applySettings(configuration.getProperties()); SessionFactory sessionFactory = configuration .buildSessionFactory(builder.build()); return sessionFactory; } public static void createEmployee() { System.out.println("****************Creating Employee*************"); Employee emp = new Employee("Jhn Doe", 44); Phone ph = new Phone(); ph.setNo("12345678"); ph.setEmp(emp); emp.setPhone(ph); Session session = getSessionFactory().openSession(); session.beginTransaction(); session.save(emp); session.getTransaction().commit(); session.close(); System.out.println("Employee Created Successfully" + emp.toString()); } }
Once, you run the Application.java as a java application, you can see entries created in table EMPLOYESS
and PHONES
with foreign key populated in table PHONES
.
I hope this article served you whatever you were looking for. If you have anything that you want to add or share then please share it below in the comment section.