Many to Many Mapping


Requirements

  • Jdk 1.7
  • Eclipse Kepler
  • MySql Database

Download JPA Many to Many Demo with jars
Download JPA Many to Many Demo without jars

In many to many mapping, one row or more one row of a table mapped with one row or more than one row of another table. In this mapping, one additional table required for mapping of two tables.
Teacher and Student is the best example of many to many mapping. One teacher can teach more than one students, one student can teach by more than one teacher.

In given example, teacher and student tables is mapped with 3rd table teacher_student. The multiple id of teacher table and multiple id of student table can mapped with teacher_student table. teacher table have two columns id and name, id is treated as primary key and name column contains the name of teacher. student table have two columns id and name, id is treated as primary key and name contains the name of student. teacher_student have two columns teacher_id and student_id, teacher_id column is the foreign key of teacher table mapped with id and student_id column is the foreign key of student table mapped with id column. The below image is the example of one to many mapping... many-to-manyjpa-hibernate-table

Step-1:- Teacher.java

Teacher is an entity class, which have three properties id and name students, id is treated as primary key, name contains name of teacher and students is type of set, set contains Student objects.
@Entity: This class is treated as entity class. If it is not declared then throws java.lang.IllegalArgumentException: Unknown entity. It contains one parameter.
Ex: @Entity(name="test"), if @Table is not defined, then it creates a table with name in @Entity(name="emp1") otherwise creates a table name of class as emp. The name of entity is by default class name. This name can be use in HQL queries like table name in normal SQL queries.
@Table is used to create table with given name.
@Id This property is treated as primary key.
@SequenceGenerator is used to create sequence in database.
@GeneratedValue is used hold the reference of sequence.
Ex:- @SequenceGenerator(name = "t_gen", ...) --> @GeneratedValue(generator = "t_gen")
@Column(name="something") This annotation used on property level. If we don't declare column annotation, then JPA is treated by default column name as property name.

@ManyToMany is used on list or set properties.
@JoinTable creates a table of name teacher_student, which have two columns teacher_id and student_id. teacher_id is mapped with Teacher.id (current class) with the help of @JoinColumn. student_id is mapped with students property in Teacher.students with the help of inverseJoinColumns attribute.
package com.groupofknowledge;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;

@Entity
public class Teacher {
    @Id
    @SequenceGenerator(name = "t_gen", sequenceName = "t_seq", allocationSize = 1,
        initialValue = 1, schema = "gok")
    @GeneratedValue(generator = "t_gen")
    private Integer id;
    private String name;

    @ManyToMany
    @JoinTable(name = "teacher_student", joinColumns = @JoinColumn(name = "teacher_id"),
        inverseJoinColumns = @JoinColumn(name = "student_id"))
    private Set<Student> students;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

Step-2:- Student.java

Student is an entity class, which have three properties id and name teachers, id is treated as primary key, name contains name of Student and teachers is type of set, set contains Teacher objects.
@Entity: This class is treated as entity class. If it is not declared then throws java.lang.IllegalArgumentException: Unknown entity. It contains one parameter.
Ex: @Entity(name="test"), if @Table is not defined, then it creates a table with name in @Entity(name="emp1") otherwise creates a table name of class as emp. The name of entity is by default class name. This name can be use in HQL queries like table name in normal SQL queries.
@Table is used to create table with given name.
@Id This property is treated as primary key.
@SequenceGenerator is used to create sequence in database.
@GeneratedValue is used hold the reference of sequence.
Ex:- @SequenceGenerator(name = "s_gen", ...) --> @GeneratedValue(generator = "s_gen")
@Column(name="something") This annotation used on property level. If we don't declare column annotation, then JPA is treated by default column name as property name.

@ManyToMany is used on list or set properties.
package com.groupofknowledge;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;

@Entity
public class Student {
    @Id
    @SequenceGenerator(name = "s_gen", sequenceName = "s_seq", allocationSize = 1,
        initialValue = 1, schema = "gok")
    @GeneratedValue(generator = "s_gen")
    private Integer id;
    private String name;

    @ManyToMany(mappedBy = "students")
    private Set<Teacher> teachers;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Teacher> getTeachers() {
        return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }
}

Step-3:- persistence.xml


Description:- persistence.xml file contains information of database. The specification of each tag is explained below...
<persistence-unit name="demo"></persistence-unit> tag has name="demo", which should match with javax.persistence.Persistence.createEntityManagerFactory("demo") in Main.java file.
<class>com.groupofknowledge.Emp</class> tag represents entity class.
In <property name="hibernate.show_sql" value="true"/> tag has a hibernate.show_sql property key, which contains boolean value. If value="true", it means query will be visible in console otherwise it will not be visible in console.
In <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> tag has a javax.persistence.jdbc.driver property key which indicates database driver details.
Example: The drivers are given as below for different database.
  • com.mysql.jdbc.Driver (MySql)
  • org.postgresql.Driver (PostgreSql)
  • oracle.jdbc.driver.OracleDriver (Oracle)
  • com.microsoft.sqlserver.jdbc.SQLServerDriver (SQL Server)
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/> has a javax.persistence.jdbc.url property key which indicates information of database connection.
The description of jdbc:mysql://localhost:3306/test is given as below...
  • localhost for local database, give IP address for remote database
  • 3306 database port
  • test database schema
Example: The different connection url's are given as below for different database.
  • jdbc:mysql://localhost:3306/test (MySql)
  • jdbc:postgresql://localhost:5432/test (PostgreSql)
  • jdbc:oracle:thin:@localhost:1521:xe (Oracle)
  • jdbc:sqlserver://MYPC\\SQLEXPRESS;databaseName=test (SQL Server)
In <property name="javax.persistence.jdbc.user" value="root"/> tag indicates the database user name.
In <property name="javax.persistence.jdbc.password" value="root" /> tag indicates the database password.
In <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> tag has a hibernate.dialect property used to generate query according to database
Example: The different dialect are given as below for different database.
  • org.hibernate.dialect.MySQLDialec (MySql)
  • org.hibernate.dialect.PostgreSQLDialect (PostgreSql)
  • org.hibernate.dialect.Oracle10gDialect (Oracle)
  • org.hibernate.dialect.SQLServerDialect (SQL Server)
In <property name="hibernate.hbm2ddl.auto" value="update"/> tag has a hibernate.hbm2ddl.auto property can contains any one value among create/update/validate/create-drop.
  • create It drops all tables and create new tables when EntityManagerFactory is initialized.
  • update It does not drop any table, it only updates the table schema.
  • validate It validates that the schema matches, make no changes to the schema of the database.
  • create-drop It drops all tables and create new tables when EntityManagerFactory is initialized. As well as it drops all tables when EntityManagerFactory is closed.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="demo">
        <class>com.groupofknowledge.Emp</class>
        <class>com.groupofknowledge.EmpDetails</class>
        <class>com.groupofknowledge.Country</class>
        <class>com.groupofknowledge.State</class>
        <class>com.groupofknowledge.Teacher</class>
        <class>com.groupofknowledge.Student</class>
        <properties>
            <property name="hibernate.show_sql" value="true"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="root" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>
After running this class, it creates two tables country and state.

Step-5:- Main.java

package com.groupofknowledge;

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

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("demo");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        Teacher t1 = new Teacher();
        t1.setName("Rajesh Sir");
        Teacher t2 = new Teacher();
        t2.setName("Naveen Sir");

        Student s1 = new Student();
        s1.setName("Ravindra");
        Student s2 = new Student();
        s2.setName("Suman");

        Set<Student> students1 = new HashSet<Student>();
        students1.add(s1);
        students1.add(s2);
        t1.setStudents(students1);

        Set<Student> students2 = new HashSet<Student>();
        students2.add(s1);
        t2.setStudents(students2);

        em.persist(t1);
        em.persist(t2);
        em.persist(s1);
        em.persist(s2);

        em.getTransaction().commit();
    }
}
The relation of country and state is given as below...
Rajesh Sir can teach to Ravindra and Suman. Naveen Sir only teach to Suman.

Result...

Teacher (Table)

id(pk) name
1 Rajesh Sir
2 Naveen Sir

student (Table)

id(pk) name
1 Ravindra
2 Suman

teacher_student (Table)

teacher_id(fk) student_id(fk)
1 1
1 2
2 2
Download JPA Many to Many Demo with jars
Download JPA Many to Many Demo without jars