One to many mapping is made between two entities where first entity can have relation with multiple second entity instances but second can be associated with only one instance of first entity. Its 1 to n relationship. For example, in any company an employee can register multiple bank accounts but one bank account will be associated with one and only one employee. In this post, we will learn to make such mapping in database using hibernate 3.
Download source code
Sections in this post Problem statement Designing the solution Using foreign key association Using a join table
Problem statement
We have to write two entities i.e. EmployeeEntity and AccountEntity such that multiple accounts can be associated with a single employee, but these accounts can not be shared between two or more employees.
Designing the solution
This problem can be solved in two different ways. One is to have a foreign key column in account table i.i EMPLOYEE_ID. This column will refer to primary key of Employee table. This way no two accounts can be associated with multiple employees. Obviously, account number needs to be unique for enforcing this restriction.
Another approach is to have a common join table lets say EMPLOYEE_ACCOUNT. This table will have two column i.e. EMP_ID which will be foreign key referring to primary key in EMPLOYEE table and similarly ACCOUNT_ID which will be foreign key referring to primary key of ACCOUNT table.
Lets write some code for both approaches.
Using foreign key association
In this approach, both entity will be responsible for making the relationship and maintaining it. EmployeeEntity should declare that relationship is One to many, and AccountEntity should declare that relationship from its end is many to one.
Lets first see the schema design.
Lets write EmployeeEntity.java
package hibernate.test.oneToMany.foreignKeyAsso;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
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.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity(name = "ForeignKeyAssoEntity")
@Table(name = "Employee", uniqueConstraints = {
@UniqueConstraint(columnNames = "ID"),
@UniqueConstraint(columnNames = "EMAIL") })
public class EmployeeEntity implements Serializable {
private static final long serialVersionUID = -1798070786993154676L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer employeeId;
@Column(name = "EMAIL", unique = true, nullable = false, length = 100)
private String email;
@Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
private String firstName;
@Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
private String lastName;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="EMPLOYEE_ID")
private Set<AccountEntity> accounts;
public Integer getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set<AccountEntity> getAccounts() {
return accounts;
}
public void setAccounts(Set<AccountEntity> accounts) {
this.accounts = accounts;
}
}
Write AccountEntity.java
package hibernate.test.oneToMany.foreignKeyAsso;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity(name = "ForeignKeyAssoAccountEntity")
@Table(name = "ACCOUNT", uniqueConstraints = {
@UniqueConstraint(columnNames = "ID")})
public class AccountEntity implements Serializable
{
private static final long serialVersionUID = -6790693372846798580L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer accountId;
@Column(name = "ACC_NUMBER", unique = true, nullable = false, length = 100)
private String accountNumber;
@ManyToOne
private EmployeeEntity employee;
public Integer getAccountId() {
return accountId;
}
public void setAccountId(Integer accountId) {
this.accountId = accountId;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public EmployeeEntity getEmployee() {
return employee;
}
public void setEmployee(EmployeeEntity employee) {
this.employee = employee;
}
}
Lets Test the code:
package hibernate.test.oneToMany;
import hibernate.test.HibernateUtil;
import hibernate.test.oneToMany.foreignKeyAsso.AccountEntity;
import hibernate.test.oneToMany.foreignKeyAsso.EmployeeEntity;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
public class TestForeignKeyAssociation
{
public static void main(String[] args)
{
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
AccountEntity account1 = new AccountEntity();
account1.setAccountNumber("Account detail 1");
AccountEntity account2 = new AccountEntity();
account2.setAccountNumber("Account detail 2");
AccountEntity account3 = new AccountEntity();
account3.setAccountNumber("Account detail 3");
//Add new Employee object
EmployeeEntity firstEmployee = new EmployeeEntity();
firstEmployee.setEmail("demo-user-first@mail.com");
firstEmployee.setFirstName("demo-one");
firstEmployee.setLastName("user-one");
EmployeeEntity secondEmployee = new EmployeeEntity();
secondEmployee.setEmail("demo-user-second@mail.com");
secondEmployee.setFirstName("demo-two");
secondEmployee.setLastName("user-two");
Set<AccountEntity> accountsOfFirstEmployee = new HashSet<AccountEntity>();
accountsOfFirstEmployee.add(account1);
accountsOfFirstEmployee.add(account2);
Set<AccountEntity> accountsOfSecondEmployee = new HashSet<AccountEntity>();
accountsOfSecondEmployee.add(account3);
firstEmployee.setAccounts(accountsOfFirstEmployee);
secondEmployee.setAccounts(accountsOfSecondEmployee);
//Save Employee
session.save(firstEmployee);
session.save(secondEmployee);
session.getTransaction().commit();
HibernateUtil.shutdown();
}
}
Output:
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into ACCOUNT (ACC_NUMBER, employee_ID) values (?, ?)
Hibernate: insert into ACCOUNT (ACC_NUMBER, employee_ID) values (?, ?)
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into ACCOUNT (ACC_NUMBER, employee_ID) values (?, ?)
Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
Using a join table
This approach uses a join table to store the associations between account and employee entities. @JoinTable annotation has been used to make this association.
Lets see how the database schema will look like:
EmployeeEntity.java
package hibernate.test.oneToMany.joinTable;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
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.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity(name = "JoinTableEmployeeEntity")
@Table(name = "Employee", uniqueConstraints = {
@UniqueConstraint(columnNames = "ID"),
@UniqueConstraint(columnNames = "EMAIL") })
public class EmployeeEntity implements Serializable
{
private static final long serialVersionUID = -1798070786993154676L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer employeeId;
@Column(name = "EMAIL", unique = true, nullable = false, length = 100)
private String email;
@Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
private String firstName;
@Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
private String lastName;
@OneToMany(cascade=CascadeType.ALL)
@JoinTable(name="EMPLOYEE_ACCOUNT", joinColumns={@JoinColumn(name="EMPLOYEE_ID", referencedColumnName="ID")}
, inverseJoinColumns={@JoinColumn(name="ACCOUNT_ID", referencedColumnName="ID")})
private Set<AccountEntity> accounts;
public Integer getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set<AccountEntity> getAccounts() {
return accounts;
}
public void setAccounts(Set<AccountEntity> accounts) {
this.accounts = accounts;
}
}
AccountEntity.java
package hibernate.test.oneToMany.joinTable;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity(name = "JoinTableAccountEntity")
@Table(name = "ACCOUNT", uniqueConstraints = {
@UniqueConstraint(columnNames = "ID")})
public class AccountEntity implements Serializable
{
private static final long serialVersionUID = -6790693372846798580L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer accountId;
@Column(name = "ACC_NUMBER", unique = true, nullable = false, length = 100)
private String accountNumber;
public Integer getAccountId() {
return accountId;
}
public void setAccountId(Integer accountId) {
this.accountId = accountId;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
}
Configuring entities in config file
We have available both entities to runtime, we have to add them in hibernate.cfg.xml file. Please note that only one set of entities should be configured in configuration file otherwise unexpected results can occur.
< ?xml version="1.0" encoding="utf-8"?> < !DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatetest</property> <property name="hibernate.connection.password">XXXXXX</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">create</property> <mapping clas="hibernate.test.oneToMany.foreignKeyAsso.AccountEntity"></mapping> <mapping clas="hibernate.test.oneToMany.foreignKeyAsso.EmployeeEntity"></mapping> </session-factory> </hibernate-configuration>
Testing the code
Now, its time to test the code. I have written following code to test above entities.
package hibernate.test.oneToMany;
import hibernate.test.HibernateUtil;
import hibernate.test.oneToMany.joinTable.AccountEntity;
import hibernate.test.oneToMany.joinTable.EmployeeEntity;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
public class TestJoinTable
{
public static void main(String[] args)
{
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
AccountEntity account1 = new AccountEntity();
account1.setAccountNumber("123-345-65454");
AccountEntity account2 = new AccountEntity();
account2.setAccountNumber("123-345-6542222");
//Add new Employee object
EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("demo-user@mail.com");
emp.setFirstName("demo");
emp.setLastName("user");
Set<AccountEntity> accounts = new HashSet<AccountEntity>();
accounts.add(account1);
accounts.add(account2);
emp.setAccounts(accounts);
//Save Employee
session.save(emp);
session.getTransaction().commit();
HibernateUtil.shutdown();
}
}
Output:
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
Hibernate: insert into EMPLOYEE_ACCOUNT (EMPLOYEE_ID, ACCOUNT_ID) values (?, ?)
Hibernate: insert into EMPLOYEE_ACCOUNT (EMPLOYEE_ID, ACCOUNT_ID) values (?, ?)
Download source code
Happy Learning !!








Dear Lokesh..I worked out your example(Using a join table) its works great…iam totally new to hibernate..i used hibernate tools to generate annotated files..but its totally different…any way i over come that issue.my only question is
Posted by Sudharsan Selvaraj | 22 February, 2013, 6:08 AMhow can i generate annotated file like you(specified in above example) ?pls reply iam very much comfortable with your example…
I am really unaware of auto code generation tools related to hibernate. Let me take some time. Probably i will be able to answer your query.
Posted by Lokesh Gupta | 22 February, 2013, 9:42 AMDear Lokesh
I am getting following ExceptionInInitializerError
what should I do?
Initial SessionFactory creation failed.java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
Posted by Rajendra Joshi | 8 February, 2013, 12:00 AMException in thread “main” java.lang.ExceptionInInitializerError
at hibernate.test.HibernateUtil.buildSessionFactory(HibernateUtil.java:22)
at hibernate.test.HibernateUtil.(HibernateUtil.java:10)
at hibernate.test.oneToMany.TestJoinTable.main(TestJoinTable.java:17)
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.hibernate.cfg.Configuration.(Configuration.java:110)
at hibernate.test.HibernateUtil.buildSessionFactory(HibernateUtil.java:15)
… 2 more
Hibernate has internal dependency on this class for logging support. Add required dependency from here.
http://commons.apache.org/logging/
Posted by Lokesh Gupta | 8 February, 2013, 3:29 AMHi, Lokesh
Posted by Sravanthi Dachepalli | 24 January, 2013, 5:22 AMThanks for the post.
If i want to update the employee entity by adding new account(‘b’) for an employee.how to go about it, in case of using join table.
What happens to the records(‘a’ account for employee e1) in Account table. How do we delete them.
let me reply based on what i understood.
you want to assign a new account to employee. so do like this:
1) read an employee entity from session.
2) add newly created account object to set of accounts.
3) finally use saveOrUpdate() method from session.
there is no need to delete any previous record. hibernate is smart enough to differentiate between attached and detached entities.
Posted by Lokesh Gupta | 28 January, 2013, 4:43 AM