Unidirectional Many to Many association mapping (without annotations)

In this post under Hibernate, I will explain how to create a unidirectional many to many association between objects using a mapping file with an example.

For our example, we will create the below two tables.

Data Definition Language


CREATE TABLE `doctor1` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(50) NOT NULL DEFAULT '0',
    `description` VARCHAR(100) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=8
;

CREATE TABLE `supplies1` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(50) NOT NULL,
    `description` VARCHAR(100) NOT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=13
;

CREATE TABLE `doctor1_supplies1` (
    `doctor_id` INT(11) NOT NULL,
    `supplies_id` INT(11) NOT NULL,
    PRIMARY KEY (`doctor_id`, `supplies_id`),
    INDEX `FK_doctor1_supplies1_supplies1` (`supplies_id`),
    CONSTRAINT `FK_doctor1_supplies1_doctor1` FOREIGN KEY (`doctor_id`) REFERENCES `doctor1` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT `FK_doctor1_supplies1_supplies1` FOREIGN KEY (`supplies_id`) REFERENCES `supplies1` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

According to above sql code, I have created three tables “doctor1”, “supplies1” and association table “doctor1_supplies1”.

In Object Oriented world, there will be many to many association between “doctor1” and “supplies1”. In other words one “doctor1” instance will have many instance of “supplies1” and the same instance of “supplies1” will belong to many instance of “doctor1”. So to create a many to many association in RDBMS, I have added a new assocation table “doctor1_supplies1” with foreign key “doctor_id” column referring to “doctor1” table, foreign key “supplies_id” column referring to “supplies1” table. Here primary key is a composite key i.e., a combination of “doctor_id” and “supplies_id”.

Next we will create java classes for the above tables

Doctor1


import java.util.Set;

public class Doctor1 {
    private int id;
    private String name;
    private String description;
    private Set supplies;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Set getSupplies() {
        return supplies;
    }
    public void setSupplies(Set supplies) {
        this.supplies = supplies;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(id).append(":");
        sb.append(name).append(":");
        sb.append(description);
        
        return sb.toString();
    }
}

Supplies1


public class Supplies1 {
    private int id;
    private String name;
    private String description;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(id).append(":");
        sb.append(name).append(":");
        sb.append(description);
        
        return sb.toString();
    }
}

Since we are creating an unidirectional many to many association meaning the navigation will be from “Doctor1” to “Supplies1”, we have added property “supplies” of type Set in “Doctor1” class.

Next we add hbm.xml file for the above java classes

Doctor1.hbm.xml


1  <?xml version="1.0"?>
2  <!DOCTYPE hibernate-mapping PUBLIC
3  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5  <hibernate-mapping>
6   <class name="Doctor1" table="Doctor1">
7       <id type="int" name="id" column="id">
8           <generator class="native"/>
9       </id>
10      <property name="name" column="name" type="string"/>
11      <property name="description" column="description" type="string"/>
12      <set name="supplies" table="DOCTOR1_SUPPLIES1" cascade="all">
13          <key column="DOCTOR_ID"/>
14          <many-to-many class="Supplies1" column="SUPPLIES_ID"/>
15      </set>
16  </class>
17 </hibernate-mapping>

In the above xml file at line 12, I have added set element with name attribute value as “supplies”, which is equal to property “supplies” in “Doctor1” class, table attribute value is the name of the association table in this example. Then a sub element key with column attribute whose value is equal to foreign key column name in the association table. Then many-to-many element with class attribute value as “Supplies1” and column attribute value equal to foreign key column name in the association table.

Supplies1.hbm.xml


1  <?xml version="1.0"?>
2  <!DOCTYPE hibernate-mapping PUBLIC
3  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5  <hibernate-mapping>
6   <class name="Supplies1" table="Supplies1">
7       <id type="int" name="id" column="id">
8           <generator class="native"/>
9       </id>
10      <property name="name" column="name" type="string"/>
11      <property name="description" column="description" type="string"/>
12  </class>
13 </hibernate-mapping>

Below is hibernate configuration file for your reference

hibernate.cfg.xml


<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://www.hibernate.org/dtd/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/examples</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
    <!-- <property name="hibernate.hbm2ddl.auto">create</property> -->
    <property name="hibernate.show_sql">true</property>
    
    <mapping resource="Doctor1.hbm.xml"/>
    <mapping resource="Supplies1.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

Below is the main code

Main Code


1  import java.util.HashSet;
2  import java.util.Set;
3  
4  import org.hibernate.Session;
5  import org.hibernate.SessionFactory;
6  
7  public class HibernateDemo14 {
8   public static void main(String[] args) {
9       SessionFactory sessionFactory = HibernateUtil.createSessionFactory();
10         
11      Doctor1 doctor1 = new Doctor1();
12      doctor1.setName("Doctor1");
13      doctor1.setDescription("Doctor1 description");
14         
15      Supplies1 supplies1 = new Supplies1();
16      supplies1.setName("Supply1");
17      supplies1.setDescription("Supply1 description");
18         
19      Supplies1 supplies2 = new Supplies1();
20      supplies2.setName("Supply2");
21      supplies2.setDescription("Supply2 description");
22         
23      Supplies1 supplies3 = new Supplies1();
24      supplies3.setName("Supply3");
25      supplies3.setDescription("Supply3 description");
26         
27      Set set1 = new HashSet();
28      set1.add(supplies1);
29      set1.add(supplies2);
30      set1.add(supplies3);
31         
32      doctor1.setSupplies(set1);
33         
34      Doctor1 doctor2 = new Doctor1();
35      doctor2.setName("Doctor2");
36      doctor2.setDescription("Doctor2 description");
37         
38      Set set2 = new HashSet();
39      set2.add(supplies1);
40      set2.add(supplies2);
41         
42      doctor2.setSupplies(set2);
43      
44      Session session = sessionFactory.openSession();
45      session.beginTransaction();
46      int id1 = (Integer)session.save(doctor1);
47      int id2 = (Integer)session.save(doctor2);
48      session.getTransaction().commit();
49      session.close();
50         
51      doctor1 = null;
52      doctor2 = null;
53         
54      session = sessionFactory.openSession();
55      doctor1 = session.load(Doctor1.class, id1);
56      System.out.println(doctor1);
57      for(Supplies1 supply : doctor1.getSupplies()) {
58          System.out.println(supply);
59      }
60      doctor2 = session.load(Doctor1.class, id2);
61      System.out.println(doctor2);
62      for(Supplies1 supply : doctor2.getSupplies()) {
63          System.out.println(supply);
64      }
65      session.close();
66      HibernateUtil.shutdown();
67  }
68 }

In the main code, at line 11 we create a new instance of Doctor1.

At line 15, 19, and 23, we create multiple instances of Supplies1 class.

At line 27 we add those instances to a set.

At line 32 we set the supplies property of doctor1 instance with the set created at line 27.

The same thing is repeated for another instance of Doctor1 class.

At line 46 and 47, we save the both instance doctor1 and doctor2 of class Doctor1.

At line 49 we close the session.

From line 54 we open a new session and retrieve both the instances of Doctor1 and loop through the related supplies.

Leave a Reply