How to Fix Duplicate Data from Hibernate Queries

by Trevor Page on September 15, 2014

Java-PodcastWe’ve covered a lot of topics on Hibernate already on this blog in a nice sequential format. If you haven’t had the pleasure of going through all the tutorials, I’d suggest going to this page and having a flip through all the topics.

How to Fix Duplicate Data from Hibernate Queries

This problem was the bane of my existence when I first started using Hibernate because I had no idea where the problem was coming from.

If you’re executing a query and finding that you have a bunch of duplicate records and haven’t a clue why, then you’re in the right place.

You see the problem is typically caused by having left joins (or optional joins) in your objects. When you have a base object, like say User and it joins to another table/object in an optional One-to-Many or optional Many-to-Many format, then you may get duplicates.

Consider this scenario… A User objects joins to the LoginHistory object, which keeps track of all the times a particular User has logged into the system. And let’s say our user has logged in many times. You’ll have a situation where you have many records in the LoginHistory table.

So what happens when you run a query that joins to the LoginHistory table? Well it will return as many rows as there are entries for that User in the LoginHistory table.

So because of this, Hibernate doesn’t massage the data for you, it just returns exactly what it got from the database. The ball is in your court to tell Hibernate what to do with records it has retrieved.

There are two solutions to this problem:

  1. Declare your joining object as a Set
  2. Make use of Distinct Root Entity Results Transformer

The Problem at a Glance

So here’s an example of the problem in action. Below you’ll see an outline of the optional one-to-many join between the User class and the LoginHistory class.

User.java

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="users")
public class User
{
  private Long userId;
  private String username;
  private String password;
  private List<LoginHistory> loginHistory;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="user_id")
  public Long getUserId()
	{
		return userId;
	}
	public void setUserId(Long userId)
	{
		this.userId = userId;
	}
	public String getUsername()
	{
		return username;
	}
	public void setUsername(String username)
	{
		this.username = username;
	}
	public String getPassword()
	{
		return password;
	}
	public void setPassword(String password)
	{
		this.password = password;
	}
	@OneToMany(cascade=CascadeType.ALL, mappedBy="user", fetch=FetchType.EAGER)
	public List<LoginHistory> getLoginHistory()
	{
		return loginHistory;
	}
	public void setLoginHistory(List<LoginHistory> loginHistory)
	{
		this.loginHistory = loginHistory;
	}
	
  
}

LoginHistory.java

package com.howtoprogramwithjava.example.persistence;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="login_history")
public class LoginHistory
{
  private Long loginHistoryId;
  private Date loggedIn;
  private User user;
  
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="login_history_id")
	public Long getLoginHistoryId()
	{
		return loginHistoryId;
	}
	public void setLoginHistoryId(Long loginHistoryId)
	{
		this.loginHistoryId = loginHistoryId;
	}
	
	@Column(name="logged_in")
	public Date getLoggedIn()
	{
		return loggedIn;
	}
	public void setLoggedIn(Date loggedIn)
	{
		this.loggedIn = loggedIn;
	}
	
	@ManyToOne(cascade=CascadeType.ALL, optional=true, fetch=FetchType.EAGER)
	@JoinColumn(name="user_id")
	public User getUser()
	{
		return user;
	}
	public void setUser(User user)
	{
		this.user = user;
	}
}

And then we have the entry in a DAO class that will query for Users by passing in a username.

  public List<User> getUserByUsername (String username)
  {
  	Session session = sessionFactory.getCurrentSession();
  	return session.createCriteria(User.class).add(Restrictions.eq("username", username)).list();
  }

So in the code directly above, we are querying the database for Users that have a username matching the String that’s being passed in.

The problem with this is that once it runs this query, it will return multiple rows if the User it finds has logged into the system more than once.

Again, it does this because it’s an optional (left) join. If you were to take a look at the query built by Hibernate, it could look something like this (assuming the username being passed in is tpage):

select * from users
left join login_history on login_history.user_id = users.user_id
where users.username = 'tpage';

This query returns multiple results (three results to be exact, in my database) as I’ve inserted three separate rows into the Login_history table that point back to the tpage user.

Alright, so hopefully you fully understand the problem, now let’s talk about some solutions to this problem.

Declaring the Join as a Set

On the parent side of the relationship, you’ll be declaring a collection of objects that embodies your *-to-Many relationship. What you’ll need to do here is to use a Set as the backing collection as opposed to something like a List (which is what we were using in the User class above).

Here’s an example of how to set it up correctly:

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.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="users")
public class User
{
  private Long userId;
  private String username;
  private String password;
  private Set<LoginHistory> loginHistory;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="user_id")
  public Long getUserId()
	{
		return userId;
	}
	public void setUserId(Long userId)
	{
		this.userId = userId;
	}
	public String getUsername()
	{
		return username;
	}
	public void setUsername(String username)
	{
		this.username = username;
	}
	public String getPassword()
	{
		return password;
	}
	public void setPassword(String password)
	{
		this.password = password;
	}
	@OneToMany(cascade=CascadeType.ALL, mappedBy="user")
	public Set<LoginHistory> getLoginHistory()
	{
		return loginHistory;
	}
	public void setLoginHistory(Set<LoginHistory> loginHistory)
	{
		this.loginHistory = loginHistory;
	}
}

Again, the key is to use a Set as the collection of child entities. So in our example above we used Set<LoginHistory>

Distinct Root Entity Results Transformer

This sounds like pure gibberish, but thankfully it’s not hard to implement. All you need to do is make sure that you set a ResultsTransformer when you’re building your query.

Remember that DAO query we talked about near the beginning of this article? I’ll show you that query again for the sake of completion:

  public List<User> getUserByUsername (String username)
  {
  	Session session = sessionFactory.getCurrentSession();
  	return session.createCriteria(User.class)
        .add(Restrictions.eq("username", username))
        .list();
  }

This query is alright, but as we’ve seen, it doesn’t work well when we have an option join and we’re dealing with a List of entities.

In the event that we NEED to use a List of entities, we can alter this query to use the ResultsTransformer. Let’s see what the corrected code looks like:

  public List<User> getUserByUsername (String username)
  {
  	Session session = sessionFactory.getCurrentSession();
  	return session.createCriteria(User.class)
        .add(Restrictions.eq("username", username))
        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
        .list();
  }

You see the difference? We just added one additional line to the query: setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) and voila! You will no longer have duplicates in your returned result set.

{ 2 comments }

Hibernate Life Cycle

by Trevor Page on September 5, 2014

Java-PodcastNow it’s time to dive into the nitty gritty of Hibernate’s mysterious inner workings.

I’m by no means an expert in Hibernate, but I do use it almost every day for my own projects, so I do know a thing or two about how it works.

One topic that had me scratching my head for ages was the Hibernate life cycle. What I mean by the life cycle is the way Hibernate interacts with Java objects at certain points in the existence of said Java objects.

Let’s start from the beginning…

What the heck is a Hibernate Life Cycle?

You see, Hibernate is picky about your Java objects. Hibernate prefers your objects to be in a certain “state”, known as the persistent state… this persistent state is one of four different states that exist inside of the hibernate persistence life cycle.

Once you have a firm grasp of the different states that an object can be in (as it pertains to Hibernate) you’ll be well on your way to mastering the Hibernate framework.

So let’s get this Hibernate persistence life cycle lesson started shall we?

Transient

A transient object is one that Hibernate has no awareness of whatsoever. It’s the first step on our journey through the life cycle. When you first create a plain old Java object (via the new keyword) this object can be thought of as being in a transient state.

So really, when you think about it, every object you’ve ever created (before you started working with Hibernate) could be thought of as being in a transient state. Again, this is the case because the database has absolutely no idea that this object is in existence.

How this “state” applies to Hibernate is that Hibernate will not be able to track transient objects and store them in the database (or update the database based on their values).

In order for the database to properly keep track of objects, is for them to be in the next state of the Hibernate persistence life cycle.

Persistent

When an object is in a persistent state, Hibernate is totally aware of it and can keep the database synchronized with it’s values.

Before we launch into the persistent state, let’s talk about how we can go from transient to persistent.

There are two main ways to make the leap from a transient object to a persistent object:

  1. Loading the object from the database via Hibernate APIs
  2. Saving the object to the database via Hibernate APIs

Ways to Save an Object

Hibernate has a few different ways to save an object to the database, but the two main ways are as follows:

  1. session.save()
  2. session.saveOrUpdate()

Invoking either of these Hibernate methods will shift your transient object into the persistent state (so long as the save is successful).

I won’t go into detail about how to use these methods, as I’ve already done so in this post.

Ways to Load an Object

There are quite a few ways to load an object from a database. Here’s a couple that I use the most:

  1. session.get()
  2. session.createCriteria()

I won’t go into detail here, as I’ve already covered how to load data from a database using Hibernate.

Why the Persistent State is King

Hibernate’s true abilities are shown when working with persistent objects.

When an object is in a persistent state within a transactional context in Hibernate, magical things happen. Namely, Hibernate will be able to synchronize the persistent object(s) when you manually invoke a save or when the transactional context is closed and committed.

To create this “transactional context” I simply rely on the Spring framework and its @Transactional annotation. You’ve seen this used already in a previous post.

But you can certainly create your own transactional context manually if you do not prefer to use the Spring framework. This just means that you’ll be writing some boilerplate transaction management code. I’m not an expert in this area at all, so if you’re interested in researching it further, there are many articles that cover transactions with Hibernate on the web.

In any case, the point I’m trying to get at here is that the majority of Hibernate’s “persistence” functionality occurs with your object is in a persistent state.

This means that if you want to add new data to the database, you’ll need to invoke the session.save() or session.saveOrUpdate() methods to take your transient object into a persistent state.

Or this means that if you want to update existing data in the database, you’ll first need to load it into an object via the aforementioned session.get() or session.createCriteria() methods.

Only when you’re modifying / updating persistent objects will Hibernate actually synchronize your changes from the Java object to your database.

Detached

Okay, so you know that the persistent state is key, but you can only be in this state while you’re inside of a transactional context.

In the world of Spring, this means that you will only be in a persistent state while inside of your DAO’s “save” methods. This is the case because Spring wraps a transactional context around each method in your DAO class. This happens because we used the @Transactional annotation at the class level.

So what happens one the flow of code leaves your DAO’s save method? Well, the transactional context is closed (via the Spring code I just talked about) and your object that was previously in the persistent state is now in a detached state.

The detached state is given to an object that was previously “attached” (persistent) but has now left the scope of the transactional context.

The “side effect” of this state is that if you make any changes to your object, Hibernate won’t be tracking them and thus won’t synchronize the changes to the database. You’ll need to invoke a session.saveOrUpdate(), a sesssion.update(), or a session.merge() in order to re-attach it and make it persistent again in a new transactional context.

This is where things can get a bit wonky though.

You see, since your object was previously persistent, Hibernate still holds a record of this object in its memory. So when your (now detached) object is passed into a session.update() method, Hibernate tries to update only the records that have changed since it last “knew” your object.

There are times when Hibernate just doesn’t know how to handle the updates and can do nothing except throw exceptions. I’ve hit this scenario before and it’s quite annoying.

Again, I’m not an expert in this field, so if anyone can explain exactly what’s going on in this particular scenario, then by all means leave a comment below.

In any case, the solution is to use the session.merge() method instead. What the merge() does is just overwrite everything (thus essentially ignoring what’s in Hibernate’s memory) with the object that you’re passing into the merge() method.

Removed

Finally, the last state in Hibernate’s persistence life cycle is the “removed” state. This happens when you have a persistent object that you’ve flagged to be deleted.

To delete a persistent object, you just invoke the session.delete() method and pass in your persistent object.

Note that you cannot properly delete a non-persistent object, so to properly delete an object you’ll need to load it using the methods we discussed earlier (going from transient to persistent).

Once you’ve deleted an object and moved to the “removed” state, you should no longer use that particular object for any reason.

Hibernate Persistence Life Cycle Diagram

If you would like to grab a copy of a really helpful diagram that outlines all the steps in the life cycle, you can download the cheat sheet here.

You’ll be able to print out this cheat sheet and stick in on your wall to impress your Mom and your friends.

hibernate_persistence_lifecycle

{ 0 comments }

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

July 28, 2014

Podcast: Play in new window | Download Since 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 […]

Read the full article →

Hibernate @ManyToOne Unidirectional Tutorial

July 23, 2014

Podcast: Play in new window | Download In 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 […]

Read the full article →

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 →