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.
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 !!
Aman
How can I fetch a subscription for a specific reader from mapping table.
Ankur
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?
Lokesh Gupta
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.
Rifaquat
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
Himanshu Singh
Hi Lokesh,
Can we make atomic transactions in hibernate.
Please guide on this.
Thanks…
shahid
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.
Alan Morelli
thank you for very good tutorial. but i’m having a lot of problems when i try to update an entity (such as Reader) and his set (Reader_subscriptions). how can i implement the update and/or the equals and hashCode methods ? here more details: https://stackoverflow.com/questions/24737145/equals-and-hashcode-of-these-entities-spring-mvc-hibernate thank you very much for tutorial
Lokesh Gupta
Looks like you was able to figure out it already.
Alan Morelli
unluckily no, i can’t update my read_subscription Set
Sayali
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?