Learn to create and manage one-to-one relationships between entities in a hibernate/JPA-based application using @OneToOne annotation. We will be learning to create the association in 4 different ways.
1. Overview
We are taking the example of an employee and his account having one to one relationship. We are assuming that
- an employee can have only one Account
- an account will be associated with one employee only
- EmployeeEntity is the owner of the relationship in a bi-directional relationship.
In hibernate, there are primarily 3 ways to create one-to-one relationships between two entities. Either way, we have to use @OneToOne annotation.
- The first technique is widely used and uses a foreign key column in one of the tables.
- The second technique uses a rather known solution of having a join table to store the mapping between the first two tables.
- The third technique is something new that uses a common primary key in both tables.
2. Using a Foreign Key Association
In this kind of association, a foreign key column is created in the owner entity. For example, we have made EmployeeEntity
owner, then an extra column "ACCOUNT_ID"
will be created in Employee
table. This column will store the foreign key for Account
table.
The table structure will be like this:

To make such an association, refer the Account
entity in EmployeeEntity
class as follow:
@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer employeeId;
@OneToOne
@JoinColumn(name="ACCOUNT_ID")
private AccountEntity account;
//Other fields, getters, setters are hidden for brevity
}
The join column is declared with the @JoinColumn annotation that looks like the @Column annotation. It has one more parameter named referencedColumnName. This parameter declares the column name in the targeted entity that will be used to 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 any side as not responsible for the relationship, the attribute mappedBy
is used. The ‘mappedBy‘ refers to the property name of the association on the owner’s side.
@Entity
@Table(name = "ACCOUNT")
public class AccountEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer accountId;
@OneToOne(mappedBy = "account")
private EmployeeEntity employee;
//Other fields, getters, setters are hidden for brevity
}
Above "mappedBy
” attribute declares that it is dependent on the owner entity for mapping.
Let’s test the above mappings:
AccountEntity account = new AccountEntity();
account.setAccountNumber("123-345-65454");
// Add new Employee object
EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("demo-user@mail.com");
emp.setFirstName("demo");
emp.setLastName("user");
// Save Account
session.persist(account);
Assertions.assertNotNull(account.getAccountId());
// Save Employee
emp.setAccount(account);
session.persist(emp);
Assertions.assertNotNull(emp.getEmployeeId());
Assertions.assertNotNull(emp.getAccount().getAccountId());
Running the above code creates the desired schema in the database and runs these SQL queries.
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
We can verify the data and mappings in both tables when we run the above program.
3. Using a Join Table
This approach is not new to all of us. Here, hibernate will create a new table that will store the primary key values from both entities. Let us start with the targeted DB structure in this technique.

In this technique, the 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. Let’s see how it is used:
@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer employeeId;
@OneToOne(cascade = CascadeType.ALL)
@JoinTable(name = "EMPLOYEE_ACCCOUNT",
joinColumns = @JoinColumn(name = "EMPLOYEE_ID"),
inverseJoinColumns = @JoinColumn(name = "ACCOUNT_ID"))
private AccountEntity account;
//Other fields, getters, setters are hidden for brevity
}
@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 the above entities generates the following SQL queries in log files:
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into EMPLOYEE_ACCCOUNT (ACCOUNT_ID, EMPLOYEE_ID) values (?, ?)
4. Using a Shared Primary Key
In this technique, hibernate will ensure that it will use a common primary key value in both tables. This way primary key of EmployeeEntity
can safely be assumed the primary key of AccountEntity
also.
The table structure will be like this:

In this approach, @PrimaryKeyJoinColumn is the main annotation to be used. Let us see how to use it.
@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer employeeId;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private AccountEntity account;
//Other fields, getters, setters are hidden for brevity
}
In AccountEntity
side, it will remain dependent on the owner entity for the mapping.
@Entity
@Table(name = "ACCOUNT")
public class AccountEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer accountId;
@OneToOne(mappedBy="account", cascade=CascadeType.ALL)
private EmployeeEntity employee;
//Other fields, getters, setters are hidden for brevity
}
Testing the above entities generates the following SQL queries in log files:
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
5. Using a Shared Primary Key with @MapsId
In this technique, hibernate assumes both the source and target share the same primary key values. When using @MapsId
, the parent-side association becomes redundant since the child-entity can be easily fetched using the parent entity identifier.
In this approach, @MapsId
is the main annotation to be used. Let’s see how to use it.
@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer employeeId;
@OneToOne
@MapsId
private AccountEntity account;
//Other fields, getters, setters are hidden for brevity
}
In AccountEntity
side, it will remain dependent on the owner entity for the mapping. So no changes are required on AccountEntity side.
@Entity
@Table(name = "ACCOUNT")
public class AccountEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer accountId;
//Other fields, getters, setters are hidden for brevity
}
Testing the above entities generates the following SQL queries in log files:
Hibernate: insert into ACCOUNT (ID, ACC_NUMBER) values (?, ?)
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME, account_ID) values (?, ?, ?, ?)
So, we have seen all 4 different ways to create one-to-one mapping supported in hibernate. I will suggest you download the source code and play with it.
Happy Learning !!
Hi Lokesh,
This article is very good, your way explanation also very good. I studied various articles on One to One and i found total 6 technical ways to define One to One mapping (all information is not defined any where, based on understanding on articles, I defined as below ways)
1. Unidirectional with Foreign Key
2. Unidirectional with Shared Primary Key.
3. Bidirectional with Foreign Key
4. Bidirectional with Shared Primary Key.
5. Bidirectional with MapsId
6. Join Table.
Requesting could you please clarify my doubt, how many ways can we define One to One mapping ?
Thanks for this Article.. I’m having query related to lazy fetching.. how to achieve the same using the above @OneToOne mapping example. Please can you help on that..
Wonderful explanation!
You wrote a great article. Earlier I spent a lot of time studying this topic but I did not understand it. Thank you!
In OneToMany relation, the many side is the owner of the relation right ? but by specifying mappedBy=user we are saying that User is the owning entity.why?
Can you please explain the above concept ?
for bi directional rules check oracle documentation:https://docs.oracle.com/cd/E19798-01/821-1841/bnbqj/index.html
Hi. I have a question about @OneToOne(cascade = CascadeType.ALL) when you implement “Using a common join table”. In this case, the cascade is on the side of EmployeeEntity. But I wonder, if the mappedby is in AccountEntity, then EmployeeEntity has a foreign key in AccountEntity, and I expect that removing, for example, a record from AccountEntity, the removal will be cascaded also in EmployeeEntity. So, shouldn’t the cascade be on the side of AccountEntity, where you also have the mapped by? Thanks for these great tutorials.
Valentino
In your “mappedBy” example no foreign key relationship maintained by EmployeeEntity. Even there is no relationship between both table . You can cross verify your sql query above. i.e.
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
there is no update query for foreign key.
Please clarify?
I think @JoinColumn instead of @PrimaryKeyJoinColumn is better choice.
Hi,
I tried foreign key column model, my question is why hibernate creates join table ’employee_acccount’ and have no use in one to one association. can any one clear my doubt?
Superb tutorial, was of great help to implement the one to one relationships in my application’s datamodel. Thanks a lot, keep rocking.
thanks , good explanation. Can you please modify the same example to add one new column in newly created table.
Never tried this. I will try in my free time.
thanks but I got How to do it…
I am pasting my example here…
1) AccountEntity.java
2)EmployeeEntity.java
3)EmpAcc.java (bean for joined table)
4)MainClass.java
In the above example balance is the new column.
Thanks for sharing your solution. Much appreciated.
Welcome….do you know gwt?
Never tried
your example is good one but i want one additional column in a newly created join table (employee_account) Can you please modify this example to add extra column
Hi ,
Can you please elobarate on mappedBy attribute.
Could not understand, even I searched so many sites.
mappedby definition says ‘I am not the owner side and mapped by other entity’
From the given example(Employee and Account) with below code.
@OneToOne(mappedBy=”account”)
private EmployeeEntity employee;
Who is not the owner? and who is Owner and what is does actually.
Please explains
This will help you : https://howtodoinjava.com/hibernate/how-to-define-association-mappings-between-hibernate-entities/
Thank you
How to insert data into database using annotation
Was learning Hibernate and went through so many tutorials online. Completely misunderstood the functionality of mappedBy till i came across this article. Good stuff guys, keep up the good work (Y)
Its great site to learn java. Thanks a lot Keep it up…………..
Great Explanation….Thanks..Sir Keep it up …
i need a help,
we have a list as field to store it in data base,
for this we have to use hibernate annotations mapping class(no hibernate mapping file should be used), pojo class object contains some fields as List, those fileds will be inserted into db as string by mapping class. if possible for you, give an example
Similar example is discussed in one to many mapping tutorial
private Set accounts;
Awsome explanation…. bookmarking site. Thanks
big Thank’s for your HELP
HI Lokesh,
Good after noon,
Currently i am working with hibernate 3. i have been trying to develop a simple hibernate project with one to many relationship.every thing is fine but i am getting error like. i have placed cfg.xml file under src folder.is correct. why i am getting error. please suggest me. as soon as…..
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Initial SessionFactory creation failed.org.hibernate.HibernateException: could not find file: hibernate.cgf.xml
Exception in thread “main” java.lang.ExceptionInInitializerError
at com.hib.pro.HibernateUtil.buildSessionFactory(HibernateUtil.java:23)
at com.hib.pro.HibernateUtil.(HibernateUtil.java:11)
at com.hib.pro.TestForeignKeyAssociation.main(TestForeignKeyAssociation.java:19)
Caused by: org.hibernate.HibernateException: could not find file: hibernate.cgf.xml
at org.hibernate.cfg.Configuration.configure(Configuration.java:1462)
at com.hib.pro.HibernateUtil.buildSessionFactory(HibernateUtil.java:18)
… 2 more
Caused by: java.io.FileNotFoundException: hibernate.cgf.xml (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:106)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1459)
… 3 more
Usually src folders have filters which cause to generate only .class files in target folder or classes folder. Copy the file in resources folder. The important thing is that file should be present in target folder (war file).
Hi
Can you please help me in
https://stackoverflow.com/questions/18895585/hibernate-version-annotation-and-object-references-an-unsaved-transient-instanc
Hi Lokesh,
Good Work. But I see a flaw in the DB design of your “Using foreign key association”. In the Employee Table one can have one account shared by the multiple employees which does not make it one to one but many to one. For that you need to put Unique constraint on Account Id column in Employee Table. Please clarify.
Abhi, you are right. It should be implemented this way. But, also that’s not core concept for this tutorial. Mixing concepts in single post, sometimes push the core concept in back seat. Which i did not wanted to do, otherwise in any code review session, I can myself blew this code. [:-)]
Wonderful information captured in one place. This blog is awesome.
Great post. Thanks for sharing the concepts.
Thanks for the article, it was to much helpful thankls a lot!!!!
Thank you sir, My name is A Aravind ,i had completed my B.Tech with an aggregate of 70%,belongs to ECE stream. Now i need to learn JAVA very effectively,i need to get placed in Java only in reputed companies. So can you please upload Core Java tutorials,JSP,SERVLETS,Struts and Hibernates. Because i am having knowledge on only Core Java,now i want to learn Struts,Hiberbates,EJB from you.
Thanking You, A.Aravind
Hello Aravind, Its good to know that you want to learn effectively. My suggestion to you is “Read more and Good”. Also, you need to learn consistently.
I will try to write some post on struts and EJBs also very soon.
By the time, if you would like to read something more in core java then follow below links: https://howtodoinjava.com/java/
https://howtodoinjava.com/best-practices/
Keep reading !!