Ultimate Guide – Association Mappings with JPA and Hibernate

Association mappings are one of the key features of JPA and Hibernate. They model the relationship between two database tables as attributes in your domain model. That allows you to easily navigate the associations in your domain model and JPQL or Criteria queries.

JPA and Hibernate support the same associations as you know from your relational database model. You can use:

You can map each of them as a uni- or bidirectional association. That means you can either model them as an attribute on only one of the associated entities or on both. That has no impact on your database mapping, but it defines in which direction you can use the relationship in your domain model and JPQL or Criteria queries. I will explain that in more details in the first example.

Many-to-One Associations

An order consists of multiple items, but each item belongs to only one order. That is a typical example for a many-to-one association. If you want to model this in your database model, you need to store the primary key of the Order record as a foreign key in the OrderItem table.

With JPA and Hibernate, you can model this in 3 different ways. You can either model it as a bidirectional association with an attribute on the Order and the OrderItem entity. Or you can model it as a unidirectional relationship with an attribute on the Orderor the OrderItem entity.

Unidirectional Many-to-One Association

Let’s take a look at the unidirectional mapping on the OrderItem entity first. The OrderItem entity represents the many side of the relationship and the OrderItem table contains the foreign key of the record in the Order table.

As you can see in the following code snippet, you can model this association with an attribute of type Order and a @ManyToOne annotation. The Order order attribute models the association, and the annotation tells Hibernate how to map it to the database.

@Entity
public class OrderItem {
@ManyToOne
private Order order;
…
}

That is all you need to do to model this association. By default, Hibernate generates the name of the foreign key column based on the name of the relationship mapping attribute and the name of the primary key attribute. In this example, Hibernate would use a column with the name order_id to store the foreign key to the Order entity.

If you want to use a different column, you need to define the foreign key column name with a @JoinColumn annotation. The example in the following code snippet tells Hibernate to use the column fk_order to store the foreign key.

That’s all about the mapping of unidirectional many-to-one associations for now. If you want to dive deeper, you should take a look at FetchTypes. I explained them in detail in my Introduction to JPA FetchTypes.

But now, let’s continue with the association mappings and talk about unidirectional one-to-many relationships next. As you might expect, the mapping is very similar to this one.

But this is most likely not the mapping you’re looking for because Hibernate uses an association table to map the relationship. If you want to avoid that, you need to use a @JoinColumn annotation to specify the foreign key column.

The following code snippet shows an example of such a mapping. The @JoinColumn annotation tells Hibernate to use the fk_order column in the OrderItem table to join the two database tables.

Bidirectional Many-to-One Associations

The bidirectional Many-to-One association mapping is the most common way to model this relationship with JPA and Hibernate. It uses an attribute on the Order and the OrderItem entity. This allows you to navigate the association in both directions in your domain model and your JPQL queries.

The mapping definition consists of 2 parts:

the to-many side of the association which owns the relationship mapping and

the to-one side which just references the mapping

Let’s take a look at the owning side first. You already know this mapping from the unidirectional Many-to-One association mapping. It consists of the Order order attribute, a @ManyToOne annotation and an optional @JoinColumn annotation.

The owning part of the association mapping already provides all the information Hibernate needs to map it to the database. That makes the definition of the referencing part simple. You just need to reference the owning association mapping. You can do that by providing the name of the association-mapping attribute to the mappedBy attribute of the @OneToMany annotation. In this example, that’s the order attribute of the OrderItem entity.

You can now use this association in a similar way as the unidirectional relationships I showed you before. But adding and removing an entity from the relationship requires an additional step. You need to update both sides of the association.

That’s all about many-to-one association mapping for now. You should also take a look at FetchTypes and how they impact the way Hibernate loads entities from the database. I get into detail about them in my Introduction to JPA FetchTypes.

Many-to-Many Associations

Many-to-Many relationships are another often used association type. On the database level, it requires an additional association table which contains the primary key pairs of the associated entities. But as you will see, you don’t need to map this table to an entity.

A typical example for such a many-to-many association are Products and Stores. Each Store sells multiple Products and each Product gets sold in multiple Stores.

Similar to the many-to-one association, you can model a many-to-many relationship as a uni- or bidirectional relationship between two entities.

But there is an important difference that might not be obvious when you look at the following code snippets. When you map a many-to-many association, you should use a Set instead of a List as the attribute type. Otherwise, Hibernate will take a very inefficient approach to remove entities from the association. It will remove all records from the association table and re-insert the remaining ones. You can avoid that by using a Set instead of a List as the attribute type.

OK let’s take a look at the unidirectional mapping first.

Unidirectional Many-to-Many Associations

Similar to the previously discussed mappings, the unidirectional many-to-many relationship mapping requires an entity attribute and a @ManyToMany annotation. The attribute models the association and you can use it to navigate it in your domain model or JPQL queries. The annotation tells Hibernate to map a many-to-many association.

Let’s take a look at the relationship mapping between a Store and a Product. The Set products attribute models the association in the domain model and the @ManyToMany association tells Hibernate to map it as a many-to-many association.

And as I already explained, please note the difference to the previous many-to-one mappings. You should map the associated entities to a Set instead of a List.

If you don’t provide any additional information, Hibernate uses its default mapping which expects an association table with the name of both entities and the primary key attributes of both entities. In this case, Hibernate uses the Store_Product table with the columns store_id and product_id.

You can customize that with a @JoinTable annotation and its attributes joinColumns and inverseJoinColumns. The joinColumns attribute defines the foreign key columns for the entity on which you define the association mapping. The inverseJoinColumns attribute specifies the foreign key columns of the associated entity.

The following code snippet shows a mapping that tells Hibernate to use the store_product table with the fk_product column as the foreign key to the Product table and the fk_store column as the foreign key to the Store table.

That’s all you have to do to define an unidirectional many-to-many association between two entities. You can now use it to get a Set of associated entities in your domain model or to join the mapped tables in a JPQL query.

Bidirectional Many-to-Many Associations

The bidirectional relationship mapping allows you to navigate the association in both directions. And after you’ve read the post this far, you’re probably not surprised when I tell you that the mapping follows the same concept as the bidirectional mapping of a many-to-one relationship.

One of the two entities owns the association and provides all mapping information. The other entity just references the association mapping so that Hibernate knows where it can get the required information.

Let’s start with the entity that owns the relationship. The mapping is identical to the unidirectional many-to-many association mapping. You need an attribute that maps the association in your domain model and a @ManyToMany association. If you want to adapt the default mapping, you can do that with a @JoinColumn annotation.

You can see an example of such a mapping in the following code snippet. The List products attribute of the Store entity owns the association. So, you only need to provide the String “products” to the mappedBy attribute of the @ManyToMany annotation.

That’s all you need to do to define a bidirectional many-to-many association between two entities. But there is another thing you should do to make it easier to use the bidirectional relationship.

You need to update both ends of a bidirectional association when you want to add or remove an entity. Doing that in your business code is verbose and error-prone. It’s, therefore, a good practice to provide helper methods which update the associated entities.

OK, now we’re done with the definition of the many-to-many association mappings. Let’s take a look at the third and final kind of association: The one-to-one relationship.

One-to-One Associations

One-to-one relationships are rarely used in relational table models. You, therefore, won’t need this mapping too often. But you will run into it from time to time. So it’s good to know that you can map it in a similar way as all the other associations.

An example for a one-to-one association could be a Customer and the ShippingAddress. Each Customer has exactly one ShippingAddress and each ShippingAddress belongs to one Customer. On the database level, this mapped by a foreign key column either on the ShippingAddress or the Customer table.

Let’s take a look at the unidirectional mapping first.

Unidirectional One-to-One Associations

As in the previous unidirectional mapping, you only need to model it for the entity for which you want to navigate the relationship in your query or domain model. Let’s say you want to get from the Customer to the ShippingAddress entity.

The required mapping is similar to the previously discussed mappings. You need an entity attribute that represents the association, and you have to annotate it with an @OneToOne annotation.

When you do that, Hibernate uses the name of the associated entity and the name of its primary key attribute to generate the name of the foreign key column. In this example, it would use the column shippingaddress_id. You can customize the name of the foreign key column with a @JoinColumn annotation. The following code snippet shows an example of such a mapping.

That’s all you need to do to define a one-to-one association mapping. You can now use it in your business to add or remove an association, to navigate it in your domain model or to join it in a JPQL query.

Bidirectional One-to-One Associations

The bidirectional one-to-one relationship mapping extends the unidirectional mapping so that you can also navigate it in the other direction. In this example, you also model it on the ShippingAddress entity so that you can get the Customer for a giving ShippingAddress.

Similar to the previously discussed bidirectional mappings, the bidirectional one-to-one relationship consists of an owning and a referencing side. The owning side of the association defines the mapping, and the referencing one just links to that mapping.

The definition of the owning side of the mapping is identical to the unidirectional mapping. It consists of an attribute that models the relationship and is annotated with a @OneToOne annotation and an optional @JoinColumn annotation.

The referencing side of the association just links to the attribute that owns the relationship. Hibernate gets all information from the referenced mapping, and you don’t need to provide any additional information. You can define that with the mappedBy attribute of the @OneToOne annotation. The following code snippet shows an example of such a mapping.

Summary

The relational table model uses many-to-many, many-to-one and one-to-one associations to model the relationship between database records. You can map the same relationships with JPA and Hibernate, and you can do that in an unidirectional or bidirectional way.

The unidirectional mapping defines the relationship only on 1 of the 2 associated entities, and you can only navigate it in that direction. The bidirectional mapping models the relationship for both entities so that you can navigate it in both directions.

The concept for the mapping of all 3 kinds of relationships is the same.

If you want to create an unidirectional mapping, you need an entity attribute that models the association and that is annotated with a @ManyToMany, @ManyToOne, @OneToMany or @OneToOne annotation. Hibernate will generate the name of the required foreign key columns and tables based on the name of the entities and their primary key attributes.

The bidirectional associations consist of an owning and a referencing side. The owning side of the association is identical to the unidirectional mapping and defines the mapping. The referencing side only links to the attribute that owns the association.

thank you for the very useful article! I’d say it’s the best explanation of JPA/Hibernate mappings I’ve read.

I have one question regarding the One-to-One example. It seems to me it’d make more sense to have FK in ShippingAddress table because Customer can exist without ShippnigAddress but ShippingAddress should not exist without Customer. Do you agree with this kind of reasoning?

Yes, that part is correct. You don’t need to persist the Order object because it’s already a managed entity. Hibernate will automatically detect all pending changes during the dirty check and flush them to the database.

That depends on the number of elements on the many-site of your associations.
If your database contains several thousand cities for each state, then you should use a unidirectional many-to-one association. I would not model it as a bidirectional association because fetching several thousand entities will create performance issues.
If the many-site doesn’t contain that many elements, I would use a bidirectional many-to-one association.

I want to share a “gotcha” for those who are new to these concepts like me. I have a ManyToMany association between User and Role. When accessing the roles for a user, the program was caught in an infinite loop culminating in a StackOverflowError. Digging through the stack trace led me to believe that the equals() and/or hashCode() were improperly implemented and included the associated ManyToMany sets (i.e. User was comparing Roles which was comparing Users, etc). Cleaning up those methods to remove the sets resolved the issue.

Thanks for the great article!
But you haven’t mentioned about the cascading types in @ManyToMany relationship part.
How is Spring Data JPA or Hibernate going to handle the relationships between entities?

In above topic : Bidirectional One-to-One Associations
Customer is owning side and refrence is also created in cutomer table , is it a preferred way or we should store customer_id in shippingAddress table.

You need to model the owning side of the association on the entity that maps the database table that contains the foreign key column. For a one-to-one association, it doesn’t matter on which side you model the foreign key.