Labels

Wednesday 19 February 2014

[HIBERNATE] one-to-one mapping using annotations

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:
foreign key association one to one
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.
join table one to one mapping
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:
shared primary key one to one
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 !!

Download source code



Source: http://howtodoinjava.com/2012/11/15/hibernate-one-to-one-mapping-using-annotations/

No comments:

Post a Comment