Hibernate Many-to-Many Mapping (JPA)

A few months ago, I wrote an article how to map the one-to-one bi-directional relations between two entities and now is the time for a simple example how to map many-to-many relation. You can find what Many-to-Many relation means in Wikipedia, and the following article only shows how it looks like in Db and how it can be mapped in Hibernate. Ready?

First of all, let’s consider a classic situation with orders and products. Briefly speaking, an order can contain a number of products, and a product can belong to a number of orders. For example, an order #123 contains headphones AudioTechnica MT100 and a microphone Sure L200; in its turn, the item headphones AudioTechnica MT100 was ordered by a few customers, and it is a part of the order #123 as well as #321. Looks pretty much clear, doesn’t it?

Now, how could it be implemented in DB? RDBMs supports only one-to-many relations and in order to implement the many-to-many relation, we have to create one more – a cross-reference table. Let’s consider the diagram. The order_product table is our cross-reference table, and it contains two primary keys to maintain one-to-many relations to order and product tables. That is it about the physical representation and let’s take a look how it works in Hibernate.

In Hibernate we need the following entities:

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

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

@Table(name = "order")
public class Order {

	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", length = 11)
	private int id;

	@Column(name = "time", length = 45)
	private Date time;

	@JoinTable(name = "order_product", joinColumns = { @JoinColumn(name = "order_id") }, inverseJoinColumns = { @JoinColumn(name = "product_id") })
	private Set products = new HashSet();

	public Order() {


	// getters and setters

@Table(name = "product")
public class Product {
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", length = 11)
	private int id;

	@Column(name = "name", length = 45)
	private String name;

	@Column(name = "description", length = 45)
	private String description;

	public Product() {


	// getters, setters

As you can see, there is no OrderProduct entity and technically, the order_product table doesn’t represent any entity. We use it as a service table

@JoinTable(name = "order_product", joinColumns = { @JoinColumn(name = "order_id") }, inverseJoinColumns = { @JoinColumn(name = "product_id") })

That is it. The many-to-many relation is a clear, simple, and powerful approach to represent data interrelation. With JPA annotations, you can map the relation within a few minutes, and the code is easy to read and maintain.

A small update. Finally, I set up my own repository (shame on me, no github because of a few reasons) and now all code is available in it.

Example Code

Category: Development, Hibernate, Java

Tagged: , ,

Leave a Reply

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.