Hibernate one-to-one mapping using annotations
If you are working on any hibernate project or you are planning to work on any in future, then you can easily understand the one-to-one relationships between several entities in your application. In this post, i will discuss variations of one-to-one mappings supported in hibernate.
Download source code
Sections in this post:
Various supported techniques
Using foreign key association
Using a common join table
Using shared primary key
For this article, I am extending the example written
for hello world example. We have two entities here:
Employee and
Account.
Various supported techniques
In hibernate there are 3 ways to create one-to-one relationships between two entities. Either way you have to use
@OneToOne annotation.
First technique is most widely used and uses a foreign key column in one to table.
Second technique uses a rather known solution of having a third table to store mapping between first two tables.
Third technique is something new which uses a common primary key value in both the tables.
Lets see them in action one by one:
Using foreign key association
In this association, a foreign key column is created in owner entity. For example, if we make EmployeeEntity owner, then a extra column “ACCOUNT_ID” will be created in Employee table. This column will store the foreign key for Account table.
Table structure will be like this:

To make such association, refer the account entity in EmployeeEntity class as follow:
1.@OneToOne
2.@JoinColumn(name="ACCOUNT_ID")
3.private AccountEntity account;
The join column is declared with the
@JoinColumn annotation which looks like the
@Column annotation. It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join.
If no @JoinColumn is declared on the owner side, the defaults apply. A join column(s) will be created in the owner table and its name will be the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column(s) in the owned side.
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 association on the owner side.
1.@OneToOne(mappedBy="account")
2.private EmployeeEntity employee;
Above “mappedBy” attribute declares that it is dependent on owner entity for mapping.
Lets test above mappings in running code:
01.public class TestForeignKeyAssociation {
03. public static void main(String[] args) {
04. Session session = HibernateUtil.getSessionFactory().openSession();
05. session.beginTransaction();
06.
07. AccountEntity account = new AccountEntity();
08. account.setAccountNumber("123-345-65454");
09.
10. // Add new Employee object
11. EmployeeEntity emp = new EmployeeEntity();
12. emp.setEmail("demo-user@mail.com");
13. emp.setFirstName("demo");
14. emp.setLastName("user");
15.
16. // Save Account
17. session.saveOrUpdate(account);
18. // Save Employee
19. emp.setAccount(account);
20. session.saveOrUpdate(emp);
21.
22. session.getTransaction().commit();
23. HibernateUtil.shutdown();
24. }
25.}
Running above code creates desired schema in database and run these SQL queries.
1.Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
2.Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
You can verify the data and mappings in both tables when you run above program..
Using a common join table
This approach is not new to all of us. Lets start with targeted DB structure in this technique.

In this technique, main annotation to be used is
@JoinTable.
This annotation is used to define the new table name (mandatory) and foreign keys from both of the tables. Lets see how it is used:
1.@OneToOne(cascade = CascadeType.ALL)
2.@JoinTable(name="EMPLOYEE_ACCCOUNT", joinColumns = @JoinColumn(name="EMPLOYEE_ID"),
3.inverseJoinColumns = @JoinColumn(name="ACCOUNT_ID"))
4.private AccountEntity account;
@JoinTable annotation is used in EmployeeEntity class. It declares that a new table EMPLOYEE_ACCOUNT will be created with two columns EMPLOYEE_ID (primary key of EMPLOYEE table) and ACCOUNT_ID (primary key of ACCOUNT table).
Testing above entities generates following SQL queries in log files:
1.Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
2.Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
3.Hibernate: insert into EMPLOYEE_ACCCOUNT (ACCOUNT_ID, EMPLOYEE_ID) values (?, ?)
Using shared primary key
In this technique, hibernate will ensure that
it will use a common primary key value in both the tables. This way primary key of EmployeeEntity can safely be assumed the primary key of AccountEntity also.
Table structure will be like this:

In this approach,
@PrimaryKeyJoinColumn is the main annotation to be used.Let see how to use it.
1.@OneToOne(cascade = CascadeType.ALL)
2.@PrimaryKeyJoinColumn
3.private AccountEntity account;
In AccountEntity side, it will remain dependent on owner entity for the mapping.
1.@OneToOne(mappedBy="account", cascade=CascadeType.ALL)
2.private EmployeeEntity employee;
Testing above entities generates following SQL queries in log files:
1.Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
2.Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
So, we have seen all 3 types of one to one mappings supported in hibernate. I will suggest you to download the source code and play with it.
Happy Learning !!
Source:
http://howtodoinjava.com/2012/11/15/hibernate-one-to-one-mapping-using-annotations/