Hibernate - One to One
Say an 'Employee' has only one 'Address' and both 'Employee' and 'Address' are Entities. In that case we will be going for a 'one to one' mapping.
Let us see the 'Employee' class:
class Employee {
String id;
String name;
Address address;
---Getters & Setters---
}
An 'Employee' can have only one 'Address'. So, in the 'Employee' class we have put:
Address address;
The 'Address' class is defined below.
class Address{
int id;
String streetName;
String city;
String pinCode;
Employee employee;
---Getters & Setters---
}
Also in the 'Address' class we have put:
Employee employee;
So, from the database point of view there is a one-to-one relationship among 'Employee' and 'Address'.
Now, since both 'Employee' and 'Address' are Entities, we have to define two mapping files for 'Employee' and 'Address':
1. Firstly in 'Employee.hbm.xml' mapping file we need to tell Hibernate that 'Employee' and 'Address' is having a 'one to one' relationship.
Employee.hbm.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<id name = "id" type = "string">
<column name = "ID">
</id>
<property name = "name" type = "string">
<column name = "NAME">
</property>
<one-to-one name="address" class="Address" cascade="all">
</class>
</hibernate-mapping>
We have used <one-to-one> tag to create a 'One to One' relationship between 'EMPLOYEE' and 'ADDRESS'. And as we know why 'cascade' is used? So that we don't have to save the 'Address' object separately in 'session.save(address)' in main() method. Since it is linked with 'Employee'. It should be saved when employee object is saved in 'session.save(employee)'.
2. Next, let's write the 'Address.hbm.xml' mapping file:
Address.hbm.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Address" table = "ADDRESS">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="foreign">
<param name="property">employee</param>
</generator>
</id>
<one-to-one name="employee" class="Employee" constrained="true"/>
<property name = "streetName" type = "string">
<column name = "STREET_NAME">
</property>
<property name = "city" type = "string">
<column name = "CITY">
</property>
<property name = "pinCode" type = "string">
<column name = "PIN_CODE">
</property>
</class>
</hibernate-mapping>
This is the mapping file where we have defined the foreign key relationship. Where we have defined 'ID' as the foreign key
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="foreign">
and mentioned the foreign key has to be linked with the primary key of 'Employee'.
<param name="property">employee</param>
Finally the above param name 'employee' is referred in 'One to One' relationship
<one-to-one name="employee" class="Employee" constrained="true"/>
In simple words we have referenced 'Employee' object in 'Address' class
class Address {
...
...
Employee employee;
}
and referenced 'Address' object in 'Employee' class
class Address {
...
...
Address address;
}
to establish a 'One to One' relationship.
3. Now that we have defined the mapping files for the Entities 'Employee' and 'Address', we will be writing the main class where we will be saving the 'Employee' data and its corresponding 'Address' data to the database using Hibernate.
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateSave {
public static void main(String[] args) {
static SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
Address address = new Address();
Address address = new Address();
address.setStreetName("Walls Street");
address.setCity("Delhi");
address.setPinCode("110012");
Employee employee = new Employee();
employee.setId(1);
employee.setName("Joe");
employee.setAddress(address);
session.save(employee);
//session.save(localAddress);
//Don't have to write the above statement as cascade="all" is set in the mapping file.
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
So, in the above example we have created an 'Address' object.
Address address = new Address();
address.setStreetName("Walls Street");
address.setCity("Delhi");
address.setPinCode("110012");
And since we are referencing 'Address' in the 'Employee' class, we have assigned the 'address' values to the 'Employee' class.
employee.setAddress(address);
and save the 'employee' object using the 'save()' method of Hibernate.
session.save(employee);
EMPLOYEE
ADDRESS
ID |
STREET_NAME |
CITY |
PIN_CODE |
1 |
Walls street |
Delhi |
110012 |
So, 'ID' column in the 'EMPLOYEE' table is the foreign key 'ID' in 'ADDRESS' table.