Hibernate / JPA One-to-Many Mappings

Hibernate one to many mapping is made between two entities where the first entity can have a relation with multiple instances of the second entity but the second can be associated with only one instance of the first entity. It is a 1 to N relationship.

For example, in any company, an employee can register for multiple bank accounts but one bank account will be associated with one and only one employee. In this hibernate one to many mapping annotation examples, we will learn to make such mappings in the database using hibernate.

1. Design Overview

We should use one to many mapping to create 1..N relationship between entities or objects.

For example, as discussed above, we have to write two entities i.e. EmployeeEntity and AccountEntity such that multiple accounts can be associated with a single employee, but one single account can not be shared between two or more employees.

This problem can be solved in two different ways.

  1. One is to have a foreign key column in the ACCOUNT table i.e. EMPLOYEE_ID. This column will refer to the primary key of Employee table. This way no two accounts can be associated with multiple employees. Obviously, the account number needs to be unique for enforcing this restriction.
  2. The second approach is to have a link table. Let’s say the table name is EMPLOYEE_ACCOUNT. This table will have two columns i.e. EMP_ID that will be a foreign key referring to the primary key in EMPLOYEE table and similarly ACCOUNT_ID which will be a foreign key referring to the primary key of ACCOUNT table.

2. Using Foreign Key Association

We are designing a unidirectional relationship where when we delete an employee then account are deleted as well. But when we delete an account (one of many) then employee is unaffected.

2.1. Create Association

Let’s first see the schema design.

one-to-many-association-in-hiberate-using-foreign-key-7284046

Then we write the entity classes.

@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable { 

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private Integer employeeId;

  @OneToMany(cascade=CascadeType.ALL)
  @JoinColumn(name="EMPLOYEE_ID")
  private Set<AccountEntity> accounts;

  //Other fields, getters, setters are hidden for brevity
}
@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
}

2.2. Demo

Let’s test the relationship and monitor the CREATE queries.

create table Employee (
 ID integer generated by default as identity,
  EMAIL varchar(100) not null,
  FIRST_NAME varchar(100) not null,
  LAST_NAME varchar(100) not null,
  primary key (ID)
)

create table ACCOUNT (
 ID integer generated by default as identity,
  ACC_NUMBER varchar(100) not null,
  EMPLOYEE_ID integer,
  primary key (ID)
)

alter table if exists ACCOUNT 
       add constraint FKmyqrmihkv5isa3tjsj01x65sr 
       foreign key (EMPLOYEE_ID) 
       references Employee
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 employee = new EmployeeEntity();
employee.setEmail("demo-user-first@mail.com");
employee.setFirstName("demo-one");
employee.setLastName("user-one");

Set<AccountEntity> accountList = new HashSet<AccountEntity>();
accountList.add(account1);
accountList.add(account2);
accountList.add(account3);

employee.setAccounts(accountList);

//Save Employee
session.persist(employee);

Program Output:

Hibernate: insert into Employee (ID, EMAIL, FIRST_NAME, LAST_NAME) values (default, ?, ?, ?)
Hibernate: insert into ACCOUNT (ID, ACC_NUMBER) values (default, ?)
Hibernate: insert into ACCOUNT (ID, ACC_NUMBER) values (default, ?)
Hibernate: insert into ACCOUNT (ID, ACC_NUMBER) values (default, ?)
Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?

3. Using Link Table

This approach uses the @JoinTable annotation to create a link table that stores the associations between account and employee entities.

3.1. Create Association

Lets see how the database schema will look like:

one-to-many-association-in-hiberate-using-join-table-5973305
One To Many association in hibernate using a join table

On EmployeeEntity, we will add the @OneToMany annotation along with @JoinTable definition. This is the owning side.

@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable { 

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private Integer employeeId;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "EMPLOYEE_ACCOUNT", 
  joinColumns = {@JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "ID")},
  inverseJoinColumns = {@JoinColumn(name = "ACCOUNT_ID", referencedColumnName = "ID")})
private Set<AccountEntity> accounts;

  //Other fields, getters, setters are hidden for brevity
}

If we want to create a bi-directional relationship then we need to use @ManyToOne association on the child side.

@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity implements Serializable { 

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private Integer employeeId;

@OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "EMPLOYEE_ACCOUNT", 
  joinColumns = {@JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "ID")},
  inverseJoinColumns = {@JoinColumn(name = "ACCOUNT_ID", referencedColumnName = "ID")})
private Set<AccountEntity> accounts;

  //Other fields, getters, setters are hidden for brevity
}

@Entity
@Table(name = "ACCOUNT")
public class AccountEntity implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private Integer accountId;

  @ManyToOne
  private EmployeeEntity employee;

  //Other fields, getters, setters are hidden for brevity
}

3.2. Demo

Now, it’s time to test the code. I have written the following code to test the above entities.

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<>();
accounts.add(account1);
accounts.add(account2);

emp.setAccounts(accounts);

//Save Employee
session.persist(emp);

Program Output:

Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?)
Hibernate: insert into ACCOUNT (ACC_NUMBER, ID) values (?, ?)
Hibernate: insert into ACCOUNT (ACC_NUMBER, ID) values (?, ?)
Hibernate: insert into EMPLOYEE_ACCOUNT (EMPLOYEE_ID, ACCOUNT_ID) values (?, ?)
Hibernate: insert into EMPLOYEE_ACCOUNT (EMPLOYEE_ID, ACCOUNT_ID) values (?, ?)

In this hibernate @OneToMany mapping annotation example using list, we learned to create 1..N relationships between two entities using foreign key association and join table techniques.

Happy Learning !!

Sourcecode on Github

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

45 thoughts on “Hibernate / JPA One-to-Many Mappings”

  1. I had 4 tables and they are related like this:

    1st Table : Columns are username, password, is active. It has a primary key username
    2nd Table : Column are user_role_id, username, role. User_role_id is primary key and username has a foreign key constraint with 1st table (username)

    3rd Table: Columns are id, role_id, comp_id. id is primary key and role_id and comp_id has foreign key constraints with 2nd (user_role_id) and 4th table (id)

    4th Table: columns are id, component_name, component_path. id is primary key

    My problem is I want to retrieve component_name and Component_path based on username.

    How to do it in Hibernate. Plz help. Stuck for many days on this.

    Reply
  2. Hi Lokesh,

    Thanks for your wonderful tutorial!!

    I have some doubts –

    1. The foreign key association example in this post is unidirectional association or a bidirectional one. I feel it is bidirectional as
    both the entities have reference to each other.

    2. In case it is bidirectional then why have we not made the Account entity as the owner of the
    relation. Why is “mappedBy” attribute not used?

    Thanks in advance,

    Rohit

    Reply
  3. Hi Lokesh Gupta,
    Thanks for the post.
    This work good for save,Update,delete,get(EmployeeEntity.class,id), but in Query.list() gives Error like this

    Hibernate: select employeeen0_.ID as ID0_0_, employeeen0_.EMAIL as EMAIL0_0_, employeeen0_.FIRST_NAME as FIRST3_0_0_, employeeen0_.LAST_NAME as LAST4_0_0_ from Employee employeeen0_ where employeeen0_.ID=?
    org.hibernate.hql.ast.QuerySyntaxException: EmployeeEntity is not mapped [from EmployeeEntity]

    can help me to fatch all Records from EmployeeEntity Table with Account details.

    Reply
  4. Hi Lokesh,
    nice explanation!!
    I have a doubt regarding account class.Nowhere you are mentioning save account object then how it is saving the account object.
    please clarify!!

    Reply
  5. Hi,

    I am not quite clear why did you use Set accounts; on EmployeeEntity? everybody uses set on OneToMany relationship is there a specific reason for it?

    thanks

    Reply
    • we can use any collection implementation like set or list, no limitations to set , but we generally use set because set takes no duplicate values so if any account is added twice it might change the entire concept so here used SET.

      Reply
  6. Hi, I have seen at different places that the annotations are placed above the getter methods. Does it make a difference if we place the annotations above the getter methods?

    Reply
  7. Thanks for the great article.

    When would be the behaivor if i add the mappedBy annotation to the end of one entiy ?

    Reply
  8. With reference to implementation of REST Api using Spring, In above given link, there are some test call say “TestForeignKeyAssociation” and “TestJoinTable”. Where do I mention this code in my application? How shall I pass two objects as request body? Do I really need to send two objects as request body? What approach shall I follow?

    Reply
      • [1] created two entity class called address and location (where LocationId is foreign key)
        [2] applied relationship in address class as “@OneToOne(cascade = CascadeType.ALL)…@JoinColumn(name = “LocationId”)…private Location location;
        [3] Now, How do I send JSON input for address and location values to controller which will further send to service and DAO class to persist?

        Reply
          • Here is an example of Spring REST. Create a POST method with request body like below:

            UserLocation {
               &quot;address&quot;: { &quot;street&quot;:&quot;data&quot;, &quot;city&quot;: &quot;data&quot;},
                &quot;location&quot;: { &quot;field1&quot;:&quot;data&quot;, &quot;field2&quot;: &quot;data&quot;},
            }

            In controller, parse this object and populate separate Location and Address entities, and store them using hibernate.

          • To parse this object, do I need to create a separate POJO (consist both address and location variables) for the same or do I just parse it as JSON and fetch it using JSONObject?

          • Thanks !! Anyways nice post.
            Can you provide some reference to implement REST API using spring security? (like, user login, limited access of information, etc…)

  9. How do I apply the same logic for Spring REST api application. Like, logic implemented in HibernateStandAlone will be applied at where? How do I take two objects as an Input? Do I really need to take input of two object or one will be sufficient?

    Reply
  10. Hi Lokesh,

    I am little confused after reading the above post. I guess this is related to Unidirectional association only. Do you have any good link for bidirectional OneToMany association?

    Thanks,
    Anurag.

    Reply
  11. Hi ….Lokesh ,
    I Dont know anout hibernate i am create database with one to many and many to one mapped table
    Tbl_FileMaster (File_id,filename,filepath) joincolumn fileid
    Tbl_Header_Master(id,header,(fileid)—/joincolumn) created now i want to use inner join on it so is it possiable to create such query in this senario

    select header with max(fileid) in Filemaster table …..
    Need Help
    Thanks !

    Reply
  12. Hi Lokesh,

    Can you please explain more about inverse property.

    I have idea how to define in entity hbm.XML file, but I am confused in case of annotations.
    I want to know how we decide about the Relationship owned in case of annotations based config.

    Thanks in advance.

    Reply
  13. Hi Lokesh, Thanks for the nice post. I have some query regarding, I have to make composite primary key in table B which is combination of B_id ,first_id without using Embedded Id.So,Is there any way to do this without creating any extra class.
    ——-
    TABLE_A
    ——-
    A_id (pk)
    [other fields]

    ——-
    TABLE_B
    ——-
    B_id
    first_id (fk TABLE_A.A_id)
    PRIMARY KEY (B_id, first_id)
    [other fields]

    Reply
    • @id
      @manytoone(“your column name”)
      declare your referenced class object like “Device device”

      @id
      @manytoone(“anothe column”)
      object anothe class that u have to mapped

      it just simple its work for me

      Reply
  14. Hi Lokesh,

    First of all thanks for putting the effort for creating the various tutorials on java.

    Now onto the question. How to get EmployeeEntity associated with AccountEntity when using jointable. Would I be able to do a @ManyToOne annotation on a field inside AccountEntity like in the example using foreign key association?

    Thanks,
    -aru

    Reply
  15. I don’t understand as to why following entries were added in hibernate.cfg.xml file

    We have already annotated the entity with mapping information.

    Reply
  16. Hi Lokesh,
    Finally,I have completed your Hibernate tutorial.I am very grateful to you.I need another assistance from you.Please provide some examples with real time scenarios struts with Hibernate integration using log4j,ANT tools..

    Reply
  17. 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
    how can i generate annotated file like you(specified in above example) ?pls reply iam very much comfortable with your example…

    Reply
  18. Dear Lokesh
    I am getting following ExceptionInInitializerError
    what should I do?

    Initial SessionFactory creation failed.java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    Exception 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

    Reply
  19. Hi, Lokesh
    Thanks 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.

    Reply
    • 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.

      Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.