In bidirectional association, we will have navigation in both direction, i.e, both side of the association will have the reference to the other side. The both side of the association will implement one of the collection interfaces, if it has the reference to the other entity.

In many to many relationship, one multiple objects can have relationship with multiple target objects. Let’s consider CD and Artist. So multiple CDs can be written by multiple Artists or multiple Artists can write multiple CDs. So we will create three tables CD, CDArtist and Artist in the database and we will see how many-to-many relationship works step by step.

Step 1. Create tables

Create table – cd

CREATE TABLE `cd` (
  `cdId` bigint(20) NOT NULL AUTO_INCREMENT,
  `cdTitle` varchar(50) NOT NULL,
  PRIMARY KEY (`cdId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

 

Create table – artist

CREATE TABLE `artist` (
  `artistId` bigint(20) NOT NULL AUTO_INCREMENT,
  `artistName` varchar(50) NOT NULL,
  PRIMARY KEY (`artistId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

 

Create table – cdartist

CREATE TABLE `cdartist` (
  `artistId` bigint(20) NOT NULL,
  `cdId` bigint(20) NOT NULL,
  PRIMARY KEY (`cdId`,`artistId`),
  KEY `FK82065EE860AB4868` (`cdId`),
  KEY `FK82065EE835296F34` (`artistId`),
  CONSTRAINT `FK82065EE835296F34` FOREIGN KEY (`artistId`) REFERENCES `artist` (`artistId`),
  CONSTRAINT `FK82065EE860AB4868` FOREIGN KEY (`cdId`) REFERENCES `cd` (`cdId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

Step 2. Create a java project in any Java based IDE and configure for hibernate jars.

Step 3. Create hibernate reverse engineering and configuration file.

Reverse Engineering File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
  <schema-selection match-catalog="hibernate_assoc"/>
  <table-filter match-name="cd"/>
  <table-filter match-name="artist"/>
</hibernate-reverse-engineering>

 Configuration 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>
    <!-- hibernate database specific dialect -->
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- hibernate database specific driver -->
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <!-- hibernate database connection URL -->
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_assoc?zeroDateTimeBehavior=convertToNull</property>
    <!-- hibernate database username -->
    <property name="hibernate.connection.username">root</property>
    <!-- show sql in console -->
    <property name="hibernate.show_sql">true</property>
    <!-- format sql in cosole for better readability -->
    <property name="hibernate.format_sql">true</property>
    <!-- which context to use for sql processing -->
    <property name="hibernate.current_session_context_class">thread</property>
    <!-- translator for HSQL -->
    <property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>
    <!-- hibernate mapping resources or files -->
    <mapping resource="in/webtuts/hibernate/domain/Artist.hbm.xml"/>
    <mapping resource="in/webtuts/hibernate/domain/Cd.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

 

Step 4. Create hibernate utility class which creates singleton SessionFactory from which Session object will be created.

package in.webtuts.hibernate.utils;
 
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
 
/**
 * Hibernate Utility class with a convenient method to get Session Factory
 * object.
 *
 * @author admin
 */
public class HibernateUtil {
 
    private static final SessionFactory sessionFactory;
 
    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml)
            // config file.
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception.
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
 
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

 

Step 5. Create mapping xml file and POJO for artist table. Look at the xml file.

 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="in.webtuts.hibernate.domain.Artist" table="artist" catalog="hibernate_assoc">
        <id name="artistId" type="java.lang.Long">
            <column name="artistId" />
            <generator class="identity" />
        </id>
        <property name="artistName" type="string">
            <column name="artistName" length="50" not-null="true" />
        </property>
        <set name="cds" table="cdartist" inverse="true" fetch="select" cascade="all">
            <key>
                <column name="artistId" not-null="true" />
            </key>
            <many-to-many column="cdId" class="in.webtuts.hibernate.domain.Cd">
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>

 

package in.webtuts.hibernate.domain;

import java.util.Set;

public class Artist implements java.io.Serializable {

    private Long artistId;
    private String artistName;
    private Set<Cd> cds;

    public Artist() {
    }

    public Artist(String artistName) {
        this.artistName = artistName;
    }

    public Artist(String artistName, Set<Cd> cds) {
        this.artistName = artistName;
        this.cds = cds;
    }

    public Long getArtistId() {
        return this.artistId;
    }

    public void setArtistId(Long artistId) {
        this.artistId = artistId;
    }

    public String getArtistName() {
        return this.artistName;
    }

    public void setArtistName(String artistName) {
        this.artistName = artistName;
    }

    public Set<Cd> getCds() {
        return this.cds;
    }

    public void setCds(Set<Cd> cds) {
        this.cds = cds;
    }

}

 

Step 6. Create mapping xml file and POJO for cd table.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="in.webtuts.hibernate.domain.Cd" table="cd" catalog="hibernate_assoc">
        <id name="cdId" type="java.lang.Long">
            <column name="cdId" />
            <generator class="identity" />
        </id>
        <property name="cdTitle" type="string">
            <column name="cdTitle" length="50" not-null="true" />
        </property>
        <set name="artists" table="cdartist" fetch="select" cascade="all">
            <key>
                <column name="cdId" not-null="true" />
            </key>
            <many-to-many column="artistId" class="in.webtuts.hibernate.domain.Artist">
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>
package in.webtuts.hibernate.domain;

import java.util.Set;

public class Cd implements java.io.Serializable {

    private Long cdId;
    private String cdTitle;
    private Set<Artist> artists;

    public Cd() {
    }

    public Cd(String cdTitle) {
        this.cdTitle = cdTitle;
    }

    public Cd(String cdTitle, Set<Artist> artists) {
        this.cdTitle = cdTitle;
        this.artists = artists;
    }

    public Long getCdId() {
        return this.cdId;
    }

    public void setCdId(Long cdId) {
        this.cdId = cdId;
    }

    public String getCdTitle() {
        return this.cdTitle;
    }

    public void setCdTitle(String cdTitle) {
        this.cdTitle = cdTitle;
    }

    public Set<Artist> getArtists() {
        return this.artists;
    }

    public void setArtists(Set<Artist> artists) {
        this.artists = artists;
    }

}

 

Step 7. Now we will create a main class for testing many-to-many using join tables.

package in.webtuts.hibernate.test;

import in.webtuts.hibernate.domain.Artist;
import in.webtuts.hibernate.domain.Cd;
import in.webtuts.hibernate.utils.HibernateUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author https://www.jeejava.com
 */
public class ManyToManyBidirectionalJoin {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            Artist a1 = new Artist();
            a1.setArtistName("abc");
            Artist a2 = new Artist();
            a2.setArtistName("klm");
            Artist a3 = new Artist();
            a3.setArtistName("xyz");

            Set<Artist> artists = new HashSet<>();
            artists.add(a1);
            artists.add(a2);

            Cd cd1 = new Cd();
            cd1.setCdTitle("Java");
            Cd cd2 = new Cd();
            cd2.setCdTitle("PHP");
            Cd cd3 = new Cd();
            cd3.setCdTitle("MySQL");

            Set<Cd> cds = new HashSet<>();
            cds.add(cd1);
            cds.add(cd2);

            a3.setCds(cds);
            cd3.setArtists(artists);

            Serializable aId = session.save(a3);
            Serializable cdId = session.save(cd3);

            System.out.println("Load from Artist");
            Artist loadArtist = (Artist) session.load(Artist.class, aId);
            System.out.println("Artist ID: " + loadArtist.getArtistId());
            System.out.println("Artist Name: " + loadArtist.getArtistName());
            List<Cd> cdList = new ArrayList<>(loadArtist.getCds());
            for (Cd cd : cdList) {
                System.out.println("Cd ID: " + cd.getCdId());
                System.out.println("Cd Title: " + cd.getCdTitle());
            }
            System.out.println();
            System.out.println("---------------------------------------------");
            System.out.println("Load from CD");
            Cd loadCd = (Cd) session.load(Cd.class, cdId);
            System.out.println("Cd ID: " + loadCd.getCdId());
            System.out.println("Cd Title: " + loadCd.getCdTitle());
            List<Artist> artistList = new ArrayList<>(loadCd.getArtists());
            for (Artist artist : artistList) {
                System.out.println("Artist ID: " + artist.getArtistId());
                System.out.println("Artist Name: " + artist.getArtistName());
            }

            transaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
            transaction.rollback();
        }
    }

}

 

Step 8. Run the main class and see the output as shown below. While we save value for artist, the below values are stored into the database tables.

inserted data into artist table

insert  into `artist`(`artistId`,`artistName`) values (1,'xyz'),(2,'abc'),(3,'klm');

inserted data into cd table

insert  into `cd`(`cdId`,`cdTitle`) values (1,'Java'),(2,'PHP'),(3,'MySQL');

inserted data into cdartist table

 insert  into `cdartist`(`artistId`,`cdId`) values (2,3),(3,3);

Console Output

Hibernate:
    insert
    into
        hibernate_assoc.artist
        (artistName)
    values
        (?)
Hibernate:
    insert
    into
        hibernate_assoc.cd
        (cdTitle)
    values
        (?)
Hibernate:
    insert
    into
        hibernate_assoc.cd
        (cdTitle)
    values
        (?)
Hibernate:
    insert
    into
        hibernate_assoc.cd
        (cdTitle)
    values
        (?)
Hibernate:
    insert
    into
        hibernate_assoc.artist
        (artistName)
    values
        (?)
Hibernate:
    insert
    into
        hibernate_assoc.artist
        (artistName)
    values
        (?)
Load from Artist
Artist ID: 1
Artist Name: xyz
Cd ID: 1
Cd Title: Java
Cd ID: 2
Cd Title: PHP

---------------------------------------------
Load from CD
Cd ID: 3
Cd Title: MySQL
Artist ID: 2
Artist Name: abc
Artist ID: 3
Artist Name: klm
Hibernate:
    insert
    into
        cdartist
        (cdId, artistId)
    values
        (?, ?)
Hibernate:
    insert
    into
        cdartist
        (cdId, artistId)
    values
        (?, ?)

 

That’s all. Thanks for your reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *