≡ Menu

Hibernate @ManyToOne Unidirectional Tutorial

Java-PodcastIn the past we have learned about database relationships, specifically the One-to-Many as well as the Many-to-Many and One-to-One and that was all good, great and grand…

But now I want to talk about how to create those same relationships inside of Hibernate.

Specifically, I want to focus on the One-to-Many relationship in Hibernate and how we go about mapping it out in our Java objects.

But before we do, a word on unidirectional and bidirectional relationships.

Unidirectional vs Bidirectional

In Hibernate, it’s possible to map all three relationships that are available in a standard database, these include:

  • One-to-One
  • One-to-Many
  • Many-to-Many

But what Hibernate also includes is the ability to make EACH of those relationships either unidirectional or bidirectional.

This means that we can have a unidirectional One-to-One and a bidirectional One-to-One mapping, as well as a unidirectional One-to-Many and a bidirectional One-to-Many, as well as a unidirectional Many-to-Many and a bidirectional Many-to-Many relationship.

That’s a lot of relationships!

So what exactly are unidirectional and bidirectional relationships?

It all comes down to Java objects.

Let’s say for example that we have a One-to-Many relationship between Employer and Employee. For any one Employer there can be Many Employees and for any given Employee there can be only one Employer.

If we convert the statement above into Java objects, here’s what that would look like:

Employer.java

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Employer
{
	private Long id;
	private String employerName;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	public Long getId()
	{
		return id;
	}
	public void setId(Long id)
	{
		this.id = id;
	}
	public String getEmployerName()
	{
		return employerName;
	}
	public void setEmployerName(String employerName)
	{
		this.employerName = employerName;
	}
}

Employee.java

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Employee
{
	private Long id;
	private String employeeName;
	private Employer employer;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	public Long getId()
	{
		return id;
	}
	public void setId(Long id)
	{
		this.id = id;
	}
	public String getEmployeeName()
	{
		return employeeName;
	}
	public void setEmployeeName(String employeeName)
	{
		this.employeeName = employeeName;
	}
	
	public Employer getEmployer()
	{
		return employer;
	}
	public void setEmployer(Employer employer)
	{
		this.employer = employer;
	}
}

Okay, so, now we have two Java objects which are enabled as Hibernate Entity objects (via the @Entity annotation). Plus we’ve got all the appropriate mappings for the columns (i.e. @Id and @GeneratedValue for the primary keys).

Also you should note that there’s one key difference between these two objects… the Employee object defines the instance variable private Employer employer as well as the appropriate getters and setters.

This is the key to mapping out a unidirectional relationship.

If we were to instantiate an instance of both of these objects we would be able to determine which Employer an Employee works for (via employee.getEmployer()) but we wouldn’t be able to determine which Employees work for a given Employer (as we have no employer.getEmployees() method).

This is the meaning of a unidirectional relationship. We can only “look” at the relationship in one way.

Now, if we wanted to make this relationship a bidirectional one, we would need to add the aforementioned employer.getEmployees() method… but I don’t want to focus on bidirectional relationships just yet.

Parent and Child Tables

Alright, so you have an idea of the difference between a unidirectional and bidirectional relationship. The reason why it’s important to understand the difference between the two is because it affects the way we will map out our code.

Given that we’re focusing on the unidirectional aspect of the relationship, this means that we are only concerned with mapping the Employer instance variable within the Employee object.

As with all Hibernate related functionality, we will need to use an annotation to tell Hibernate how we’d like to map out our relationship.

But before I discuss those details we need to figure out one last concept… parent and child tables.

With a One-to-Many relationship, the child table is the one that houses the foreign key. So in our example, the foreign key will be placed into the Employee table. This is just the way it works with a One-to-Many relationship, the foreign key is always in the “Many” side of the relationship.

Now that we’ve isolated which is the child table (employee) and which is the parent table (employer) we can go a little deeper into the Hibernate mapping annotations.

@OneToMany vs @ManyToOne

Note that there are two different annotations for mapping a One-to-Many relationship in Hibernate:

  • @OneToMany
  • @ManyToOne

The reason that there are two different annotations is that we need to be able to tell Hibernate which object is the child/many part of the relationship and which object is the parent/one side of the relationship.

We are able to tell Hibernate which object is the parent object by assigning the @OneToMany annotation to the appropriate getter method… and of course we are able to tell Hibernate which object is the child object by assigning the @ManyToOne annotation to the appropriate getter method.

Now, keeping in mind that we’re only concerned with the unidirectional relationship at the moment, I need to let you in on a secret. To properly map a unidirectional One-to-Many relationship, you only need to use the @ManyToOne annotation. This may seem a bit counter-intuitive, but that’s how Hibernate works. You need to map the child/many side of the relationship and only the child/many side.

This fact works nicely with the example classes that I’ve outlined above, let’s take a look at what changes we’ll need to make to the child class (Employee) in order to enable Hibernate’s relationship functionality:

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

@Entity
public class Employee
{
	private Long id;
	private String employeeName;
	private Employer employer;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	public Long getId()
	{
		return id;
	}
	public void setId(Long id)
	{
		this.id = id;
	}
	public String getEmployeeName()
	{
		return employeeName;
	}
	public void setEmployeeName(String employeeName)
	{
		this.employeeName = employeeName;
	}

    // HERE IS THE NEW ANNOTATION CODE WE'VE ADDED
    @ManyToOne(cascade=CascadeType.ALL)
	public Employer getEmployer()
	{
		return employer;
	}
	public void setEmployer(Employer employer)
	{
		this.employer = employer;
	}
}

You’ll notice that all the code is the same except for the addition of the @ManyToOne annotation.

We place this annotation at the method level on the getter method for the object that we’d like to join with. Since we’re joining to the Employer class, we put the annotation above the getEmployer() method.

One other thing to note is the cascade that we have assigned inside the annotation.

Cascades in Hibernate

The concept of cascading is pretty straight-forward and it deals with keeping the data in a nice organized state.

Let’s say for example that we have inserted a couple of employers and three employees into our database. It might look something like this:

Employer Table
id employer_name
1 Employer 1
2 Employer 2
Employee Table
id employee_name employer_id
1 Trevor Page 1
2 John Doe 1
3 Jane Doe 2

Here we have two employees who are assigned to Employer 1, and one employee who is assigned to Employer 2.

What would happen if Employer 1 went out of business? All of the employees would likely be let go and wouldn’t work at Employer 1 anymore. This is a fact that can be automatically “handled” by Hibernate. It’s called a cascade delete.

When someone deletes Employer 1, Hibernate can be told (via cascading rules) to automatically delete any child rows that point to Employer 1. So when Employer 1 is delete, so will the employees “Trevor Page” and “John Doe” as they are associated with Employer 1.

The same concept is applied to inserting new values into the database via Hibernate.

In the example code above, we only assign a relationship to the child object via the @ManyToOne() annotation. This means that if we perform an insert on the child row, Hibernate will automatically create the parent row based on where the child row is pointing.

Let’s take a look at this as a Java example. I’ve gone ahead and created a basic Controller that will perform the insertion of the records:

@Controller
public class HomeController
{
  @Autowired
  EmployeeDao employeeDao;
  
	@RequestMapping("test")
	public String test (ModelMap model)
	{
		Employer employer = new Employer();
		employer.setEmployerName("Employer 1");
		
		Employee employee1 = new Employee();
		employee1.setEmployeeName("Trevor Page");
		employee1.setEmployer(employer);
		
		Employee employee2 = new Employee();
		employee2.setEmployeeName("John Doe");
		employee2.setEmployer(employer);
		
	  employeeDao.save(employee1);	
	  employeeDao.save(employee2);
		return "testPage";
	}
}

The main things to concern yourself with in the code above is everything inside of the test() method. I’ve included all of this code for the sake of completion, but I don’t want you to get bogged down in the details outside of the test method.

The important things to note in the code above are that we’re actually creating Java objects just like we would if we weren’t using Hibernate. We instantiate instances of the Employer object as well as two Employee objects. After setting the names of both the employer and employees, we take one critical step in this process… we set the instance of the Employer object inside of each of the Employee objects.

The process of assigning the employer to the employees is critical, and if you think about it, it makes sense. We do the same thing in the database table right? We have an employer_id column inside of the employee table! So we’re really just mimicking the database layout inside of our Java code… easy peasy!

Once we have done this, we invoke the save() method on the EmployeeDao object for each of our Employee objects. So the question is, what does the employeeDao.save() method do? I’ll show you:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.howtoprogramwithjava.example.persistence.Employee;

@Transactional
@Repository
public class EmployeeDao
{
  @Autowired
  SessionFactory sessionFactory;
  
  public void save (Employee employee)
  {
  	Session session = sessionFactory.getCurrentSession();
  	
  	session.save(employee);
  }
	
}

All the EmployeeDao does is just grab the session and save the object.

Once this session.save(employee) method is invoked, this is where hibernate will try to insert the actual employee into the database. It will realize that there’s a relationship set and will also realize that the parent row hasn’t been inserted yet, so it will first insert the parent “employer” row, then it will insert the child “employee” row as expected.

If the appropriate “employer” row already exists in the database, then it will just insert the child row and assign the appropriate foreign key to the child row.

Done and done! So there you have it, you now know how to create a One-to-many relationship with the Hibernate framework and actually create and insert the data via Java code. Very powerful stuff.

As always, if you want to be on the cutting edge of these Java tutorials and receive updates on when I’m putting on free webinars and doing give-aways please join my mailing list by putting in your email address in the popup below. When you do you’ll instantly receive one free gift from me (and plenty more in the future). I look forward to seeing you again soon!

{ 63 comments… add one }
  • Raed October 31, 2014, 6:03 am

    Dear Trevor what shall i say GREAT GREAT X 9999…… ∞

    thanks

  • Pratik December 1, 2014, 11:20 pm

    Great explanation.
    thanks and keep up the good work.

  • Anonymous December 5, 2014, 6:17 am

    Nicely explained. Thanks for the post.

  • Vinod December 25, 2014, 12:28 am

    Man this is super examples, thanks a lot ,, you rocks !!!!!! best of luck

  • Akash December 30, 2014, 2:57 pm

    Hey, Thanks a lot for the tutorial! But how does hibernate identify if the parent row already exists? In the above example if I run the code again it would insert a new employer with the same name right? How can I avoid this?

    • Trevor Page January 6, 2015, 2:38 pm

      Hibernate relies on you to set the “ID” of the object. If the ID is set, then hibernate interprets that as meaning that the row already exists and it will just perform an update (if you invoke saveOrUpdate). If you don’t set the ID on the object, then hibernate will insert another row (again, if you invoke saveOrUpdate)

      • Shraddha Patel September 26, 2017, 2:02 am

        How to set the “ID” of the object?
        Do we have to use @JoinColumn annotation for that?

  • sherif January 15, 2015, 11:05 pm

    Great Post!
    I am just wondering, ” how to tweak the above code to show all employees working under specific employer?” My concern is how to build the opposite unidirectional relational.

  • Anonymous April 2, 2015, 1:41 pm

    this article does not explain the most important part how to utilize this on the presentation layer. say you put employer into model and pass it to the view … how to do extract employees for this employer if you have only unidirectional relationship

    you can’t just access it using ${employer.employee}

  • Bharat April 14, 2015, 12:45 am

    Hey Thanks for the very informative article. I have one question though, if suppose I need to find the “list of employees” that an employer has under him/her and I am not interested in which employer an employee is associated with so does that make it a bidirectional relationship or is it still in one direction? Secondly, where should I be adding the “OneToMany” and “ManyToOne” annotations in this case. Assume I have an instance variable named “private List employees;” in my Employer class. Please help. Thank in advance! 🙂

  • Jimmy May 5, 2015, 4:01 am

    Thanks so much for your post. It seems in most case we should use many-to-one and it is easy to understand. But I do see other place they use one-to-many, which is very hard to understand. could you give some example or explain in what situation one-to-many can be used? Thanks.

  • nikhil July 19, 2015, 12:55 pm

    well explained but i’d be grateful if the same was explained with respect to xml mapping that is used at my workplace. Also bring out a page on version number and how it plays a crucial role vis a vid inserting and updating the database and how incorrect usage can prove to be such a pain

  • provisota August 26, 2015, 3:39 am

    Hi! Great post, thanks. But how about to delete ONE of Employee from Employee list, when several Employees already presented in this list? Did not it lead to foreign key constraint violation, because of CascadeType.ALL in @ManyToOne cascade option? And actually, how to do this (delete only ONE of Employee) in the right way, with this @ManyToOne unidirectional relationship?

  • Mykhaylo September 15, 2015, 9:49 pm

    Is it OK to specify @JoinColumn annotation on unidirectional @ManyToOne relationship? And what is a difference if we don’t use it. Thanks.

    • Trevor Page September 18, 2015, 10:38 am

      Off the top of my head I believe it’s okay. Using the @JoinColumn annotation allows you to specify which of the columns you want to use as the join and it allows you to name the column as well.

      If you don’t use the @JoinColumn, then I believe Hibernate just defaults to using the @Id field as the join.

      It’s been a while since I’ve thought about Hibernate, so like I said, this is just off the top of my head. The easiest thing for you to do would just be to test it yourself and see what happens. It’s a great way to learn!

  • krishna September 16, 2015, 2:45 am

    Great work… it is great tutorial

  • abhi October 1, 2015, 6:29 am

    How to insert and save mukltiple mployers.i am using hibernate template and annotations, error: A different object with the same identifier value was already associated with the session.
    Mention the syntax.

  • Anup October 3, 2015, 2:15 am

    Nice explanation. Especially the diff between unidirectional and bidirectional.
    However it would be great if you club “mappedBy” annotation along with your tutorial as well.

    • Anonymous October 3, 2015, 2:16 am

      oops my bad.You already have explained in the next tutorial. 🙂

  • viswesh October 14, 2015, 5:28 am

    Absolutely awesome. Tremendously simplified Explanation. Thank you for your time

  • Anonymous November 3, 2015, 2:18 am

    cool

  • Kate January 4, 2016, 8:39 am

    Hi, explain please why you annotate getters with associations (@onetomany @manytoone and etc) , but not corresponding fields?
    I saw this in many examples but it’s nowhere explained why not fields..

    • Trevor Page January 7, 2016, 11:41 am

      Great question Kate.

      You can do either or… but I’ve found that for some scenarios, things can get a bit wonky if you choose to annotate the fields (as opposed to the getters). So I always annotate the getters (and just the getters) with my JPAs

  • abhi January 16, 2016, 2:21 am

    hi, could u explain me many-to-one bidirectional using collections too.PLZ

  • Manish January 29, 2016, 1:09 am

    Thanks for the explanation, really helped!!

  • Nilanjan February 9, 2016, 8:35 am

    Please add me

  • Improper Bostonian April 10, 2016, 2:23 am

    Most excellent machan!

  • Ken April 11, 2016, 9:08 am

    Dear Sir, what a great explanation.
    Do you also have a blog explaining Hibernate and JPARepository ? 🙂

  • Pranay Sampat April 13, 2016, 8:06 pm

    Very well explained. Nice work

  • Pranay Sampat April 13, 2016, 8:08 pm

    Trevor,

    Don’t associate getters and setters because sometimes we need to add fetch type to it?

  • Poonam May 2, 2016, 10:48 pm

    wonderful explanation, i had been trying a lot to understand these associations , couldn’t get information, this example is so easy to understand. thanks for sharing

  • Sagar May 10, 2016, 4:02 am

    Greatly explained. Cleared the concept.

    Thankyou

  • pankaj May 31, 2016, 8:22 pm

    The best thing about this tutorial is , it is simple to understand. Thanks for sharing.

  • nesh July 22, 2016, 1:44 pm

    This was a great article 🙂

  • Anonymous July 25, 2016, 6:26 am

    child records should not be delete while parent is deleting. how we should do this?

  • Rishi August 7, 2016, 5:11 pm

    You are hurting my mind with Java, in a good way. Thank you for doing this. 5 starts and two thumbs up

  • BLU Eli September 7, 2016, 8:45 pm

    Thanks for the post

  • ishwor September 12, 2016, 1:26 pm

    straight to the point :))

  • Charaviz September 21, 2016, 8:53 am

    Awesome stuff…. !!!

  • Kiran October 24, 2016, 9:02 am

    hi Trveor,

    I have 3 tables Student,College and University.

    Student table has columns student ID, Student name and College ID.
    College table has columns College ID, College name and University ID.
    University table has columns University ID,University Name.
    (ID columns bveing primary keys in all three tables)

    I am trying to save college object in DB using Spring+JPA+JSON.
    I have a ManyToOneMapping with University in College.

    I have used cascase ALL.

    If i save college with a new University everything works fine.

    But if i try to save a college with an already existing University it gives “org.hibernate.PersistentObjectException: detached entity passed to persist:” error.

    Please help!!

  • Nrups October 27, 2016, 5:39 am

    Hi Trevor
    Need a help in my scenario….
    I m using Hibernate and i want to make foreign key in its own table… so how i can make setter & getter for this???
    I hope you understand what i meant!!!!

  • Gangs November 15, 2016, 3:57 pm

    NOW THESE MAPPINGS ARE EASY PEASY… THANKS MUCH FOR WONDERFUL EXPLANATION

  • Rajinder Kaur December 7, 2016, 2:03 pm

    The BEST

  • Sudheer December 8, 2016, 12:20 pm

    Awesome Explanation

  • Sudheer Pratap December 8, 2016, 12:23 pm

    Awesome

  • sarath December 29, 2016, 2:40 am

    Its wrong code. Where is the employer_id mapping in employee table.

  • Shanika January 9, 2017, 1:34 am

    Clear explanation, Great work ! thanks

  • Muru Natanasigamani January 20, 2017, 8:50 am

    I have one question. How do you return the collection of employees for an Employer. Since the Employer entity does not know about employee, because of the unidirectional mapping. We write a query to get list of Employees for a employer. Can somebody chime in.

  • Arpit February 19, 2017, 4:21 pm

    unidirectional Many-to-Many ?

  • Yeswanth February 24, 2017, 1:48 am

    Perfect !!!
    So clear. I rarely found this kind of explanation in any other resource.
    Thankyou and keep going.

  • Anuj March 7, 2017, 5:37 am

    It was the best article that anyone can ever get on hibernate Mapping.
    Thanks a lot to person who so ever wrote this.

  • dip halani May 12, 2017, 8:56 am

    what if there are one too many relationships like college(1) to events(1..*),
    I only want to insert college at the moment and events will be added in future,
    how to handle this scenario?

  • Sagar May 15, 2017, 2:04 am

    Hi Trevor,

    Excellent blog! I’m glad to have stumbled upon this.
    I have a question: You have mentioned cascade=CascadeType.ALL in the Employee class. I think this is not correct because going by this logic, if an employee is deleted, the associated employer is also deleted. Or am I missing something?

    • Josh August 24, 2017, 7:20 pm

      You should not use cascade in this relationship (at least not in this way). Deleting the parent will result in an constraint violation, because the parent does not know about the children, which means that it cannot delete them first. Deleting the child will try to delete the parent, which will work if there is only one child with that parent, however if there are multiple children it will also result in a constraint violation.

  • sudheer October 27, 2017, 5:03 am

    thats some good stuff, neatly explained…

  • Tapio Niemelä January 16, 2018, 12:40 pm

    Thanks for clear article, however one question arises:

    In DDD and with Spring JPA we have Aggregate roots, which should be the parent/top objects with dedicated Repositories. With example from this article it would need to be vice-versa; one has Repository for Employee. Or have I misunderstood? What can be done about it?

  • Venkat January 18, 2018, 1:13 am

    Perfect Explanation… Thanks Trevor

  • Karthik March 8, 2018, 3:53 am

    The best tutorial available on the internet on hibernate association mappings.

  • Paramvir Singh March 27, 2019, 7:40 am

    Thanks for the helpful article but I can’t agree on one point here, the one where you said:-

    ‘Now, keeping in mind that we’re only concerned with the unidirectional relationship at the moment, I need to let you in on a secret. To properly map a unidirectional One-to-Many relationship, you only need to use the @ManyToOne annotation’

    You said that we’re going to create a one to many relationship which means the entity that is in consideration (the one side) will be able to fetch the many side, but instead what we did is that we actually fetched the one side from many side which is actually ManyToOne relationship .

    So to summarise- by using @ManyToOne annotation we actually created the Many to One relationship not One to Many.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.