Hibernate @ManyToMany Unidirectional and Bidirectional

by Trevor Page on August 21, 2014

Hibernate @ManyToMany Unidirectional

The Many-to-Many relationship can be best described by example.

The example we’re going to use is that of the relationship between an Author and a Book.

Authors publish Books, and Books have Authors. Any one Author can publish many Books, and any one Book can be published by many Authors, so this is why it is a many to many relationship.

Other examples of the many to many relationship are Students to Courses and Employees to Projects.

Let’s take a look at how the unidirectional many-to-many relationship is created using Hibernate:

Author.java

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

@Entity
public class Author
{
  private Long authorId;
  private String authorName;
	
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  public Long getAuthorId()
	{
		return authorId;
	}
	public void setAuthorId(Long authorId)
	{
		this.authorId = authorId;
	}
	
	@Column(name="author_name")
	public String getAuthorName()
	{
		return authorName;
	}
	public void setAuthorName(String authorName)
	{
		this.authorName = authorName;
	}
}

Book.java

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.ManyToMany;

@Entity
public class Book
{
  private Long bookId;
  private String bookName;
  private Set<Author> authors;
  
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  public Long getBookId()
	{
		return bookId;
	}
	public void setBookId(Long bookId)
	{
		this.bookId = bookId;
	}
	
	@Column(name="book_name")
	public String getBookName()
	{
		return bookName;
	}
	public void setBookName(String bookName)
	{
		this.bookName = bookName;
	}
	@ManyToMany(cascade=CascadeType.ALL)
	@JoinTable(name="author_book", joinColumns=@JoinColumn(name="book_id"), inverseJoinColumns=@JoinColumn(name="author_id"))
	public Set<Author> getAuthors()
	{
		return authors;
	}
	public void setAuthors(Set<Author> authors)
	{
		this.authors = authors;
	}
}

The only thing that’s different from the other relationships we’ve already looked at in the past two posts is the use of the join table. A join table is necessary to facilitate the many-to-many relationship. Since we need to use this 3rd table in the database schema to map out this many to many relationship, we’ll need to let Hibernate know how to construct this join table.

We first specify the name of the table “author_book”. The convention for naming the join table is to concatenate the two names of the tables that make up the relationship, hence “author_book”. The next thing we must do is specify the names of the foreign keys that will exist inside the table. These foreign keys are referred to as the join column and inverse join column. The join column in this case refers to the name of the foreign key that belongs to the object that we’re currently coding… which in this case is the Book object. So that’s why we specify “book_id” as the join column. The inverse join column is just the name of the foreign key that belongs to the OTHER table, which is the Author table, hence “author_id”.

With that code in place, we’ve now successfully mapped out our relationship! All that’s left is to understand how to create the objects and assign the appropriate values to them.

Code to Persist Data

Set<Author> howToProgramWithJavaAuthor = new HashSet<Author>();
		Set<Author> howToProgramWithJava2ndAuthors = new HashSet<Author>();
		Set<Author> howToPlayGuitarAuthor = new HashSet<Author>();
		
		Author author = new Author();
		author.setAuthorName("Trevor Page");
		howToProgramWithJavaAuthor.add(author);
		
		Author author2 = new Author();
		author2.setAuthorName("John Doe");
		
		howToProgramWithJava2ndAuthors.add(author);
		howToProgramWithJava2ndAuthors.add(author2);
		howToPlayGuitarAuthor.add(author2);
		
		Book book = new Book();
		book.setBookName("How to Program with Java");
		
		Book book2 = new Book();
		book2.setBookName("How to Program with Java 2nd Edition");
		
		Book book3 = new Book();
		book3.setBookName("How to Play Guitar");
		
		book.setAuthors(howToProgramWithJavaAuthor);
		book2.setAuthors(howToProgramWithJava2ndAuthors);
		book3.setAuthors(howToPlayGuitarAuthor);
		
		dao.save(book);
		dao.save(book2);
		dao.save(book3);

In the unidirectional relationship (just like with the other two types of relationships), we set the parent values into the children. So in this case we set the Authors into the Book objects. Make sure you don’t forget that we need to assign a Set of Authors into the Book objects.

We then save each Book object via our standard DAO object and we’re all set!

Hibernate @ManyToMany Bidirectional

Author.java

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.ManyToMany;

@Entity
public class Author
{
  private Long authorId;
  private String authorName;
	private Set<Book> books;
  
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="author_id")
  public Long getAuthorId()
	{
		return authorId;
	}
	public void setAuthorId(Long authorId)
	{
		this.authorId = authorId;
	}
	
	@Column(name="author_name")
	public String getAuthorName()
	{
		return authorName;
	}
	public void setAuthorName(String authorName)
	{
		this.authorName = authorName;
	}
	
	@ManyToMany(cascade=CascadeType.ALL, mappedBy="authors")
	public Set<Book> getBooks()
	{
		return books;
	}
	public void setBooks(Set<Book> books)
	{
		this.books = books;
	}
}

The main difference between the bidirectional and unidirectional many to many relationship is the fact that we need to create the instance variable that will hold references to Books in the Author object. This makes sense since we’re creating the bidirectional many to many relationship, which means we should be able to access the objects that are related to both the Books and Authors from either object.

Knowing this, we assign a Set of Books to the Author object.

On the getter method, we create the @ManyToMany mapping with the key mappedBy property to indicate that this is the parent side of the relationship (the owning side).

This is the case because we can have an Author without a Book object (I decided that an Author can be in the process of writing a book, but hasn’t yet published it, so an Author can exist without a Book).

Book.java

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.ManyToMany;

@Entity
public class Book
{
  private Long bookId;
  private String bookName;
  private Set<Author> authors;
  
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="book_id")
  public Long getBookId()
	{
		return bookId;
	}
	public void setBookId(Long bookId)
	{
		this.bookId = bookId;
	}
	
	@Column(name="book_name")
	public String getBookName()
	{
		return bookName;
	}
	public void setBookName(String bookName)
	{
		this.bookName = bookName;
	}
	@ManyToMany(cascade=CascadeType.ALL)
	@JoinTable(name="author_book", joinColumns=@JoinColumn(name="book_id"), inverseJoinColumns=@JoinColumn(name="author_id"))
	public Set<Author> getAuthors()
	{
		return authors;
	}
	public void setAuthors(Set<Author> authors)
	{
		this.authors = authors;
	}
}

The Book class remains the same as in the unidirectional code above.

But the way we persist the objects will change:

Code to Persist Data

Set<Author> howToProgramWithJavaAuthor = new HashSet<Author>();
		Set<Author> howToProgramWithJava2ndAuthors = new HashSet<Author>();
		Set<Author> howToPlayGuitarAuthor = new HashSet<Author>();
		
		Set<Book> trevorsBooks = new HashSet<Book>();
		Set<Book> johnsBooks = new HashSet<Book>();
		
		Author author = new Author();
		author.setAuthorName("Trevor Page");
		howToProgramWithJavaAuthor.add(author);
		
		Author author2 = new Author();
		author2.setAuthorName("John Doe");
		
		howToProgramWithJava2ndAuthors.add(author);
		howToProgramWithJava2ndAuthors.add(author2);
		howToPlayGuitarAuthor.add(author2);
		
		Book book = new Book();
		book.setBookName("How to Program with Java");
		
		Book book2 = new Book();
		book2.setBookName("How to Program with Java 2nd Edition");
		
		Book book3 = new Book();
		book3.setBookName("How to Play Guitar");
		
		trevorsBooks.add(book);
		trevorsBooks.add(book2);
		johnsBooks.add(book2);
		johnsBooks.add(book3);
		author.setBooks(trevorsBooks);
		author2.setBooks(johnsBooks);
		book.setAuthors(howToProgramWithJavaAuthor);
		book2.setAuthors(howToProgramWithJava2ndAuthors);
		book3.setAuthors(howToPlayGuitarAuthor);
		
		dao.save(author);
		dao.save(author2);

This looks like a big jumble of code, but the only thing we’ve done is add the code to assign the other half of the relationship. This means that we need to now create Sets that represent the books. We assign the appropriate Books into these new Sets and assign them to the Authors.

Now the only difference is that we save the Authors, as that’s how it’s done with the bidirectional relationships… the unidirectional relationships require that you save the child side via DAOs.

{ 4 comments }

Hibernate @OneToOne Annotation

by Trevor Page on August 7, 2014

One-to-One Unidirectional Relationship

Since you’ve already learned about the ins and outs of how unidirectional one-to-many and bidirectional one-to-many relationships work, it’s time to learn about the One-to-One relationships.

We will start things off with the unidirectional One-to-One relationship and how it’s set up in Hibernate.

First thing is first, you need to understand how a One-to-One relationship is actually set up in a database. Once you understand that the child table declares the parent’s primary key as the child’s primary key, then we can get moving with the Hibernate stuff!

For this example, we are going to use the One-to-One relationship between an Employee and their Address. The Address table will be set up as follows:

Address Table
Column Data Type
employee_id int(11)
street_address varchar(255)
city varchar(255)
region varchar(255)
zip_code varchar(10)
country varchar(255)

So knowing this, let’s have a look at what our Java Entity Object should look like for the Address:

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Entity
public class Address
{
	private Long employeeId;
	private Employee employee;
	private String streetAddress;
	private String city;
	private String region;
	private String zipCode;
	private String country;
	
	@Id
	@GeneratedValue(generator="myGenerator")
	@GenericGenerator(name="myGenerator", strategy="foreign", parameters=@Parameter(value="employee", name = "property"))
	public Long getEmployeeId()
	{
		return employeeId;
	}
	public void setEmployeeId(Long employeeId)
	{
		this.employeeId = employeeId;
	}
	
	@OneToOne(cascade=CascadeType.ALL)
	@JoinColumn(name="employee_id")
	public Employee getEmployee()
	{
		return employee;
	}
	public void setEmployee(Employee employee)
	{
		this.employee = employee;
	}
	@Column(name="street_address")
	public String getStreetAddress()
	{
		return streetAddress;
	}
	public void setStreetAddress(String streetAddress)
	{
		this.streetAddress = streetAddress;
	}
	public String getCity()
	{
		return city;
	}
	public void setCity(String city)
	{
		this.city = city;
	}
	public String getRegion()
	{
		return region;
	}
	public void setRegion(String region)
	{
		this.region = region;
	}
	@Column(name="zip_code")
	public String getZipCode()
	{
		return zipCode;
	}
	public void setZipCode(String zipCode)
	{
		this.zipCode = zipCode;
	}
	public String getCountry()
	{
		return country;
	}
	public void setCountry(String country)
	{
		this.country = country;
	}
}

Here are the topics of interest for our code above:

  1. We made sure to create an employeeId field as well as an employee object
  2. We use the @OneToOne annotation with a cascade on the getter method for the employee object (not the employeeId)
  3. Since the employeeId will not be a regular old auto generated value, we cannot use the regular @GeneratedValue logic that we used for the One-to-Many scenario
  4. We need to create our own @GenericGenerator and tell it how it should work

The One-to-One relationship requires some “extra” code because it has a special property of inheriting the foreign key from the parent table (Employee) and using it as the primary key of the child table (Address). To facilitate this property, we need to be sure that the primary key on the child table actually references the primary key of the parent table.

This is done in Java by creating an employeeId on our Address object (instead of creating an address_id).

We also declare an Employee object: we always need to maintain an actual real object reference, right? That’s the whole point of a relationship!

The curve-ball here is that we’ll need to specify the @JoinColumn for our employee‘s getter method. We do this because if we didn’t, Hibernate would create a second column named employeeId (without the underscore) in our Address table, which would be confusing and a waste of space! So we need to help Hibernate by letting it know which column is our join column in our one-to-one relationship.

Okay, so now we’re almost there, we just need to put the logic in that will tell Hibernate how to hook up our child’s primary key with the parent’s key. To do this, we need to create our own ID generator via the @GenericGenerator annotation.

With the @GenericGenerator annotation, we need to give it some information for it to work properly. First off, we name it whatever we like, for my example I just named it "myGenerator" but this is completely up to you. We also tell it what ID generation strategy to use, usually we use the “AUTO” strategy, but in this case we know that we want it to be a foreign key, so we use the “foreign” strategy.

Lastly, we need to tell the @GenericGenerator where the actual relationship exists. In our case, our @OneToOne relationship exists via the employee object, so we point it to that object via the use of the @Parameter annotation.

Oh, and let’s not forget to point our @GeneratedValue annotation to our newly minted customer @GenericGenerator via the generator="myGenerator" property.

And presto! We have a functional unidirectional One-to-One relationship. Bravo.

You should use the same basic procedures to persist the data as we did in the unidirectional one-to-many with our controller and DAO. For this example we’d create an AddressDao which just invokes a session.saveOrUpdate() on the Address object.

We would then instantiate our Address object and populate everything that we can (except the actual employeeId field, as we’ll need to leave that blank so it knows to perform an insert and not an update). It would look something like this:

Address address = new Address();
address.setStreetAddress("10 Capreol Ct");
address.setCity("Toronto");
address.setRegion("Ontario");
address.setCountry("Canada");
address.setEmployee(anEmployeeObject);
address.setZipCode("M1C 3L8");

addressDao.save(address);

One-to-One Bidirectional Relationship

The final piece in our One-to-One relationship puzzle is to outline how to create the bidirectional relationship.

This part is actually pretty straight-forward as we’ll just implement the same steps we did in the bidirectional one-to-many relationship.

We will add an Address object as an instance variable in our class definition for the Employee object. We will then put an @OneToOne annotation on the getter method and be sure to assign the mappedBy property to complete the join. Here’s what it would look like:

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

@Entity
public class Employee
{
	private Long id;
	private String employeeName;
	private Employer employer;
	private Address address;
	
	@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;
	}
	@ManyToOne(cascade=CascadeType.ALL)
	public Employer getEmployer()
	{
		return employer;
	}
	public void setEmployer(Employer employer)
	{
		this.employer = employer;
	}
	@OneToOne(cascade=CascadeType.ALL, mappedBy="employee")
	public Address getAddress()
	{
		return address;
	}
	public void setAddress(Address address)
	{
		this.address = address;
	}
}

The only thing that will need to change after this is how we actually save/persist the data. In the unidirectional situation, we invoked the save on the child (Address) object. When we’re dealing with a bidirectional relationship, we need to invoke the save on the parent (Employee) object.

Let’s take a look at how that plays itself out:

Address address = new Address();
address.setStreetAddress("10 Capreol Ct");
address.setCity("Toronto");
address.setRegion("Ontario");
address.setCountry("Canada");
address.setEmployee(anEmployeeObject);
address.setZipCode("M1C 3L8");

anEmployeeObject.setAddress(address);

employeeDao.save(anEmployeeObject);

After instantiating the Address object and setting the appropriate fields, we need to make sure to set the Address object on the Employee object to complete the bidirectional associations.

Remember, in a bidirectional relationship the parent points to the child and the child points to the parent:

  • address.setEmployee(anEmployeeObject);
  • anEmployeeObject.setAddress(address)

Then we invoke the save on the parent (Employee) object and we are good to go!

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!

{ 0 comments }

Quick announcement and favor…

by Trevor Page on August 4, 2014

Intro to Databases & SQLHey there fellow Coder,

I’m VERY close to finishing my long-awaited course on Databases and SQL.

I’ve been working up to this moment for the better part of a year now, but I’m finally going to wrap it up. I’ll be releasing it near the end of this month (August 2014).

This course will be entirely focused on “Creating, designing and managing databases.” It will include a series of about 20 video tutorial lessons and assignments. It is going to be a complete brain dump of everything that I know about “creating, designing and managing databases.”

I’m going to outline the principles of how to create a well designed database system, as well as the four main areas for managing data within a database. These tutorials will include a detailed explanation of the Structured Query Language that is used to communicate with databases.

HOWEVER, I need your help. Before I finalize everything and “send it off” for production, I need to make sure I have covered everything.

That is where YOU come in. Could you please take a few minutes to answer this super-short survey? There is really only one thing I want to ask you…

What are your two top questions about “Creating, designing and managing a database” that I absolutely NEED to answer in this training course? Please shoot me your answers in the form below:

{ 0 comments }

Hibernate @OneToMany Bidirectional Relationship

by Trevor Page on July 28, 2014

Java-PodcastSince we’ve already learned about the unidirectional @ManyToOne relationship, we can now move on to talking about what a bidirectional relationship is like, when using Hibernate.

The term “bidirectional” literally means “functioning in two directions”, which is the concept that we will apply in our relationships between two Java objects. When we have a bidirectional relationship between objects, it means that we are able to access Object A from Object B, and Object B from Object A.

We can apply this logic to our real world coding example that we saw in the last post. The example we will use is the relationship between an Employer and an Employee. Previously, we only defined a unidirectional relationship, so we could only access the Employer from the Employee object and not vice-versa.

Now let’s take a look at how to transform our existing unidirectional relationship into a bidirectional one.

Bidirectional @OneToMany Relationship – Employer/Employee

The first step in transforming our unidirectional relationship into a bidirectional relationship is to add the missing reference from the Employer to the Employee.

One critical thing to remember here is that there’s a difference between a reference from the One-to-Many side and the Many-to-One side.

When you traverse from the “Many” side to the “One” side, you only need to make reference to one object, which is why the Employee class holds a single reference to an Employer class via the private Employer employer instance variable.

However, when you traverse from the “One” to the “Many” side, you will need to hold a reference to MANY objects.

Does that make sense? Many-to-One equals one reference, One-to-Many equals many references.

So what will this look like? Well, it means that the Employer will need to hold many references to its Employees, and we accomplish this by storing them as a Collection.

In this example I will use a Set of Employee objects in my Employer class file like so:

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;
	private Set employees;
	
	@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;
	}
	
	@OneToMany(cascade=CascadeType.ALL, mappedBy="employer")
	public Set getEmployees()
	{
		return employees;
	}
	public void setEmployees(Set employees)
	{
		this.employees = employees;
	}
}

What you may have also noticed was that we added the @OneToMany annotation to the getEmployees() method. This is needed so that Hibernate understands that this is the second part of the relationship/link between the Employer and Employee.

So just like we have the @ManyToOne annotation in the Employee class, we also have the @OneToMany annotation in the Employer class… you see? Bidirectional!

Now, I haven’t yet explained what that pesky mappedBy="employer" means…

Using the mappedBy Property on Bidirectional One-to-Many Relationship

The funny thing is that you don’t actually need to use the mappedBy property, but your database will be quite a mess if you don’t.

So I like to say that it’s mandatory to use the mappedBy property when creating a bidirectional relationship in Hibernate. And yes, I did mean to refer to ALL bidirectional relationships with that previous statement.

The mappedBy property is what we use to tell Hibernate which variable we are using to represent the parent class in our child class.

If you were to look at the class definition for the child class (Employee) you will see that we have declared an instance variable called employer, which is what we used to establish our relationship. All we are doing here is we are telling the Employer class which variable the Employee class is using to create the relationship.

So! Since we declared the Employer variable with the name employer, this is what we need to put in the mappedBy property of the @OneToMany annotation.

For those of you who haven’t already seen it, here’s what the Employee class looks like (note that we haven’t made any changes to this class when we had initially created our unidirectional relationship in the last post):

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;
	}
	@ManyToOne(cascade=CascadeType.ALL)
	public Employer getEmployer()
	{
		return employer;
	}
	public void setEmployer(Employer employer)
	{
		this.employer = employer;
	}
}

Putting our Bidirectional Relationship to Use

Okay, so now that we’ve created the blueprint for our bidirectional relationship, now we need to put in the supporting code to actually test this stuff out!

In the previous post we had created an EmployeeDao object which we used to save our employee1 and employee2 objects into the database in a unidirectional manner… but… now that we’ve changed our code around to use a bidirectional relationship, we need to change the way we persist our data.

As I mentioned, we previously used the EmployeeDao to persist our data, but now that we’ve switched to bidirectional we will need to use an EmployerDao to carry out our wishes! The EmployerDao will be identical to the EmployeeDao except that it will persist an Employer object. Here’s what it looks like:

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.Employer;

@Transactional
@Repository
public class EmployerDao
{
  @Autowired
  SessionFactory sessionFactory;
  
  public void save (Employer employer)
  {
  	Session session = sessionFactory.getCurrentSession();
  	
  	session.save(employer);
  }
	
}

Now the only missing piece is to show you how to actually persist data using this new bidirectional One-to-Many mapping.

I’ve set up the test code in a Controller class, I’ll include all of the code for the sake of completion, but all you really need to be concerned with is how the code inside the test method works.

import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.howtoprogramwithjava.example.dao.EmployerDao;
import com.howtoprogramwithjava.example.persistence.Employee;
import com.howtoprogramwithjava.example.persistence.Employer;

@Controller
public class HomeController
{
  @Autowired
  EmployerDao employerDao;
  
	@RequestMapping("test")
	public String test (ModelMap model)
	{
		Employer employer = new Employer();
		employer.setEmployerName("Employer 1");
		
		Set employees = new HashSet();
		
		Employee employee1 = new Employee();
		employee1.setEmployeeName("Trevor Page");
		employee1.setEmployer(employer);
		employees.add(employee1);
		
		Employee employee2 = new Employee();
		employee2.setEmployeeName("John Doe");
		employee2.setEmployer(employer);
		employees.add(employee2);
		
		employer.setEmployees(employees);
		
		employerDao.save(employer);

		return "testPage";
	}
}

Inside of the test method is where all the magic happens.

What you need to know is that since we have a bidirectional relationship, this means we need to assign objects to EACH side of the relationship. This means that we need to populate both the employee.setEmployer() as well as the employer.setEmployees(). It’s absolutely critical that this be done correctly.

To persist all the objects correctly you’ll need to follow these generic steps:

  1. Instantiate/Load parent object
  2. Instantiate/Load child objects
  3. Set the parent object in the child objects
  4. Create a collection of child objects
  5. Set the collection of child objects on the parent
  6. Save the parent

Note: To observe best coding practices, the code I’ve put into this Controller class is usually best placed in a Service class, but to keep things as simple as possible for this tutorial I’ve just placed all the code directly into the Controller.

Alright! We’re done! You now know how to create a One-to-Many bidirectional relationship with Hibernate. Congrats!

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!

{ 5 comments }

Hibernate @ManyToOne Unidirectional Tutorial

by Trevor Page on July 23, 2014

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!

{ 1 comment }

Hibernate – Creating Data Access Objects (DAOs)

July 15, 2014

Podcast: Play in new window | Download Data Access Objects – What are they? Data Access Objects (or DAOs for short) are used as a direct line of connection and communication with our database. DAOs are used when the actual CRUD (CRUD = Create, Read, Update, Delete) operations are needed and invoked in our Java […]

Read the full article →

Hibernate @Entity – Mapping Your Java Beans

July 8, 2014

Podcast: Play in new window | Download Now that you’ve learned how to set up your first Hibernate Java project it’s time to put that fresh new configuration to work! What You’ll Learn The focus of this podcast / blog post is to teach you how to create the connection between your Java objects and […]

Read the full article →

Hibernate Persistence for Beginners

July 3, 2014

Podcast: Play in new window | Download Ladies and Gentlemen! We have finally hit a milestone in our journey of learning Java, we are now done talking specifically about SQL and are moving on to talk about persistence frameworks. Let’s start with the most obvious question first… What is a Persistence Framework? As the name […]

Read the full article →

SQL Subquery

June 25, 2014

Podcast: Play in new window | Download The SQL Subquery Now that you’ve learned about SQL Joins, aggregate functions and the group by keyword, it’s time we moved on to our final topic in our SQL tutorial series. Today you’ll be learning all about SQL Subqueries, how to use them and when you should use […]

Read the full article →

SQL Group By

June 16, 2014

Podcast: Play in new window | Download SQL Group By After having talked about all the SQL Aggregate functions, there’s one more topic that goes hand in hand with what we’ve already learned… The group by keyword. This particular keyword allows us to take a bunch of data and mash it all together into matching […]

Read the full article →