Hibernate many to many mapping annotation example

Hibernate many to many mapping is made between two entities where one can have relation with multiple other entity instances. For example, for a subscription service SubscriptionEntity and ReaderEntity can be two type of entities. Any subscription can have multiple readers, where a reader can subscribe to multiple subscriptions.

In this hibernate tutorial, we will learn to create many to many mapping in database using hibernate.

Table of contents

Hibernate many to many mapping design
Owner entity
Mapped entity
Configure entities in hibernate config file
Demo

1. Hibernate many to many mapping design

To demonstrate many to many mapping using hibernate annotations, we will associate two entities i.e. ReaderEntity and SubscriptionEntity.

Their database schema should look like this. Using these tables, any application can save multiple associations between readers and subscriptions.

many-to-many-hibernate-mapping-3294174

2. Owner entity

Owner entity is the entity which is responsible make making the association and maintaining it. In our case, I am making ReaderEntity the owner entity. @JoinTable annotation has been used to make this association.

package hibernate.test.manyToMany.joinTable;

import java.io.Serializable;
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;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity(name = "ReaderEntity")
@Table(name = "READER", uniqueConstraints = {
		@UniqueConstraint(columnNames = "ID"),
		@UniqueConstraint(columnNames = "EMAIL") })

public class ReaderEntity implements Serializable 
{
	private static final long serialVersionUID = -1798070786993154676L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID", unique = true, nullable = false)
	private Integer readerId;

	@Column(name = "EMAIL", unique = true, nullable = false, length = 100)
	private String email;

	@Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
	private String firstName;

	@Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
	private String lastName;

	@ManyToMany(cascade=CascadeType.ALL)
	@JoinTable(name="READER_SUBSCRIPTIONS", joinColumns={@JoinColumn(referencedColumnName="ID")}
										, inverseJoinColumns={@JoinColumn(referencedColumnName="ID")})	
	private Set<SubscriptionEntity> subscriptions;

	//Getters and setters
}

3. Mapped entity

Our mapped entity is SubscriptionEntity which is mapped to ReaderEntity using “mappedBy” attribute.

package hibernate.test.manyToMany.joinTable;

import java.io.Serializable;
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.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity(name = "SubscriptionEntity")
@Table(name = "SUBSCRIPTION", uniqueConstraints = {
		@UniqueConstraint(columnNames = "ID")})

public class SubscriptionEntity implements Serializable 
{
	private static final long serialVersionUID = -6790693372846798580L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID", unique = true, nullable = false)
	private Integer subscriptionId;

	@Column(name = "SUBS_NAME", unique = true, nullable = false, length = 100)
	private String subscriptionName;
	
	@ManyToMany(mappedBy="subscriptions")
	private Set<ReaderEntity> readers;

	//Getters and setters
}

4. Configuring entities in hibernate config file

We have make available both entities to runtime. To do so, we have to add them in hibernate.cfg.xml file.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatetest</property>
        <property name="hibernate.connection.password">XXXXXX</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
		<property name="hbm2ddl.auto">create</property>
        <mapping class="hibernate.test.manyToMany.joinTable.ReaderEntity"/>
        <mapping class="hibernate.test.manyToMany.joinTable.SubscriptionEntity"/>
    </session-factory>
</hibernate-configuration>

5. Hibernate many to many annotation mapping example

Now, its time to test the code. I have written following code to test above entities and their many to many relationship.

package hibernate.test.manyToMany;

import hibernate.test.HibernateUtil;
import hibernate.test.manyToMany.joinTable.*;

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

import org.hibernate.Session;

public class TestJoinTable
{
	public static void main(String[] args) 
	{
		Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
       
		//Add subscription
		SubscriptionEntity subOne = new SubscriptionEntity();
		subOne.setSubscriptionName("Entertainment");
		
		SubscriptionEntity subTwo = new SubscriptionEntity();
		subTwo.setSubscriptionName("Horror");
		
		Set<SubscriptionEntity> subs = new HashSet<SubscriptionEntity>();
		subs.add(subOne);
		subs.add(subTwo);
		
		//Add readers
		ReaderEntity readerOne = new ReaderEntity();
		readerOne.setEmail("demo-user1@mail.com");
		readerOne.setFirstName("demo");
		readerOne.setLastName("user");
		
		ReaderEntity readerTwo = new ReaderEntity();
		readerTwo.setEmail("demo-user2@mail.com");
		readerTwo.setFirstName("demo");
		readerTwo.setLastName("user");
		
		Set<ReaderEntity> readers = new HashSet<ReaderEntity>();
		readers.add(readerOne);
		readers.add(readerTwo);
		
		readerOne.setSubscriptions(subs);
		readerTwo.setSubscriptions(subs);

		session.save(readerOne);
		session.save(readerTwo);
		
		session.getTransaction().commit();
		HibernateUtil.shutdown();
	}
}

Program Output:

Hibernate: insert into READER (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into SUBSCRIPTION (SUBS_NAME) values (?)
Hibernate: insert into SUBSCRIPTION (SUBS_NAME) values (?)
Hibernate: insert into READER (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into READER_SUBSCRIPTIONS (readers_ID, subscriptions_ID) values (?, ?)
Hibernate: insert into READER_SUBSCRIPTIONS (readers_ID, subscriptions_ID) values (?, ?)
Hibernate: insert into READER_SUBSCRIPTIONS (readers_ID, subscriptions_ID) values (?, ?)
Hibernate: insert into READER_SUBSCRIPTIONS (readers_ID, subscriptions_ID) values (?, ?)

In this example, we learned about hibernate many to many join table using annotations.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

10 thoughts on “Hibernate many to many mapping annotation example”

  1. Hi Lokesh,

    Some people say avoid using many-to-many as hibernate best practices. There are different explanation which are not clear to me. Is it true? Could you please explain why?

    Reply
    • Hi Ankur, I have not read any such best practice till date so please provide any relevant link discussing the M-M relationship as avoidable best practice. I believe if someone says it to avoid it then he must give any good example where this relationship is inefficient AND then what is the alternative? Just saying M-M relationship is bad, is not enough for me.

      Reply
  2. Hi,

    I have updated my project with hibernate 4 . I have tried Many to Many relationship but it is not saving in third join table.any kind of experiment in Many many relationship it giving error but does not shows what kind of error it is.It just shows error starting tomcat. need help

    Reply
  3. hi lokesh,
    I am stuck in problem related to implementing which mapping in hibernate.
    Following is my scenario:-
    I have user table and image table.
    There are 4 images where I need to store x,y coordinates of images against each user so I have created image table as
    userid,imageid,xcodnt,ycodnt.There could be no primary key in this table as imageid & userid will be multiple as:-
    1 1
    1 2
    1 3
    1 4
    2 1
    2 2
    2 3
    2 4.
    Could you please help me out this.
    Your help will be highly appreciated.
    Thanks in advance.

    Reply
  4. All you posts for hibernate mapping were really very useful for understanding . Can you please put up a post for many to many mapping with extra attributes in join table?

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.