Friday 26 December 2014

Hibernate : Many-To-Many mapping


In Many-to-many relationships, one or more rows in a table are associated with one or more rows in another table.

For example,
One employee can work in multiple projects.
One project can have more than one employee

package myFirstHibernate;

import java.util.ArrayList;
import java.util.List;

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

@Entity
public class Project {
 @Id @GeneratedValue
 private int projectId;
 
 private String projectName;
 
 @ManyToMany(mappedBy = "projects")
 private List<Employee> emp = new ArrayList<Employee> ();

 public int getProjectId() {
  return projectId;
 }

 public void setProjectId(int projectId) {
  this.projectId = projectId;
 }

 public String getProjectName() {
  return projectName;
 }

 public void setProjectName(String projectName) {
  this.projectName = projectName;
 }

 public List<Employee> getEmp() {
  return emp;
 }

 public void setEmp(List<Employee> emp) {
  this.emp = emp;
 }
  
}

package myFirstHibernate;

import java.util.ArrayList;
import java.util.List;

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


@Entity
public class Employee {
 @Id @GeneratedValue
 private int id;
 private String firstName;
 private String lastName;
 
 @ManyToMany(cascade=CascadeType.ALL)
 List<Project> projects = new ArrayList<Project> ();

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public List<Project> getProjects() {
  return projects;
 }

 public void setProjects(List<Project> projects) {
  this.projects = projects;
 }
  
}

hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

  <session-factory>
  
   <!--  Database Connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost/sample</property>
    <property name="connection.username">root</property>
    <property name="connection.password">tiger</property>
    
    <!-- Enable the logging of all the generated SQL statements to the console -->
    <property name="show_sql">true</property>
    
    <!-- Format the generated SQL statement to make it more readable, -->
    <property name="format_sql">false</property>
    
    <!-- Hibernate will put comments inside all generated SQL statements to hint what’s the generated SQL trying to do -->
    <property name="use_sql_comments">false</property>
    
    <!-- This property makes Hibernate generate the appropriate SQL for the chosen database. -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    
    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">create</property>
    
    <!-- mappings for annotated classes -->
    <mapping class="myFirstHibernate.Employee" />
    <mapping class="myFirstHibernate.Project" />
    
  </session-factory>
  
</hibernate-configuration>

package myFirstHibernate;


import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class TestEmployee {
 
 /* Step 1: Create session factory */
 private static SessionFactory getSessionFactory() {
  Configuration configuration = new Configuration().configure();
  StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
  applySettings(configuration.getProperties());
  SessionFactory factory = configuration.buildSessionFactory(builder.build());
        return factory;
    }
 
 public static void main(String args[]){
  Employee emp1 = new Employee();
  
  emp1.setFirstName("Hari Krishna");
  emp1.setLastName("Gurram");
  
  
  Project pjt1 = new Project();
  Project pjt2 = new Project();
  Project pjt3 = new Project();

  pjt1.setProjectName("A350");
  pjt2.setProjectName("OLTP");
  pjt3.setProjectName("mobileNews");
  
  pjt1.getEmp().add(emp1);
  pjt2.getEmp().add(emp1);
  pjt3.getEmp().add(emp1);
  
  
  emp1.getProjects().add(pjt1);
  emp1.getProjects().add(pjt2);
  emp1.getProjects().add(pjt3);
  
  /* To persist data */
  SessionFactory sessionFactory = getSessionFactory();
  Session session = sessionFactory.openSession();
  session.beginTransaction();
  session.save(emp1);
  session.save(pjt1);
  session.save(pjt2);
  session.save(pjt3);
  session.getTransaction().commit();
  session.close(); 
  
 }
}

Run TestEmployee class, you will get output like below.

Hibernate: drop table if exists Employee
Hibernate: drop table if exists Employee_Project
Hibernate: drop table if exists Project
Hibernate: create table Employee (id integer not null auto_increment, firstName varchar(255), lastName varchar(255), primary key (id))
Hibernate: create table Employee_Project (emp_id integer not null, projects_projectId integer not null)
Hibernate: create table Project (projectId integer not null auto_increment, projectName varchar(255), primary key (projectId))
Hibernate: alter table Employee_Project add constraint FK_f5aalkv5e77py6w477g4ufdye foreign key (projects_projectId) references Project (projectId)
Hibernate: alter table Employee_Project add constraint FK_lxvhcr3thmq8jp4ky2re93scf foreign key (emp_id) references Employee (id)
Dec 21, 2014 2:57:03 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into Employee (firstName, lastName) values (?, ?)
Hibernate: insert into Project (projectName) values (?)
Hibernate: insert into Employee_Project (emp_id, projects_projectId) values (?, ?)
Hibernate: insert into Employee_Project (emp_id, projects_projectId) values (?, ?)
Hibernate: insert into Employee_Project (emp_id, projects_projectId) values (?, ?)


If you want, you can change Join table name and column names using @JoinTable annotation.

@JoinTable(name="emp_project_mapping",
                   joinColumns={@JoinColumn(name="emp_id")}, 
                   inverseJoinColumns={@JoinColumn(name="pjt_id")})
List<Project> projects = new ArrayList<Project> ();

Update Employee.java like below.

package myFirstHibernate;

import java.util.ArrayList;
import java.util.List;

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

@Entity
public class Employee {
 @Id @GeneratedValue
 private int id;
 private String firstName;
 private String lastName;
 
 @ManyToMany(cascade=CascadeType.ALL)
 @JoinTable(name="emp_project_mapping", 
      joinColumns={@JoinColumn(name="emp_id")},  
      inverseJoinColumns={@JoinColumn(name="pjt_id")})
 List<Project> projects = new ArrayList<Project> ();

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public List<Project> getProjects() {
  return projects;
 }

 public void setProjects(List<Project> projects) {
  this.projects = projects;
 }
  
}


Rerun TestEmployee class, you will get output like below.

Hibernate: drop table if exists Employee
Hibernate: drop table if exists Project
Hibernate: drop table if exists emp_project_mapping
Hibernate: create table Employee (id integer not null auto_increment, firstName varchar(255), lastName varchar(255), primary key (id))
Hibernate: create table Project (projectId integer not null auto_increment, projectName varchar(255), primary key (projectId))
Hibernate: create table emp_project_mapping (emp_id integer not null, pjt_id integer not null)
Hibernate: alter table emp_project_mapping add constraint FK_3f1n22jvmbpdlmwjv1x8lmrgb foreign key (pjt_id) references Project (projectId)
Hibernate: alter table emp_project_mapping add constraint FK_rib962avfewq8oou4r3jyj61i foreign key (emp_id) references Employee (id)
Dec 21, 2014 3:11:23 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into Employee (firstName, lastName) values (?, ?)
Hibernate: insert into Project (projectName) values (?)
Hibernate: insert into emp_project_mapping (emp_id, pjt_id) values (?, ?)
Hibernate: insert into emp_project_mapping (emp_id, pjt_id) values (?, ?)
Hibernate: insert into emp_project_mapping (emp_id, pjt_id) values (?, ?)


MySQL table structures looks like below.

mysql> describe emp_project_mapping;
+--------+---------+------+-----+---------+-------+
| Field  | Type    | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| emp_id | int(11) | NO   | MUL | NULL    |       |
| pjt_id | int(11) | NO   | MUL | NULL    |       |
+--------+---------+------+-----+---------+-------+
2 rows in set (0.03 sec)

mysql> describe employee;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| firstName | varchar(255) | YES  |     | NULL    |                |
| lastName  | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql> describe project;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| projectId   | int(11)      | NO   | PRI | NULL    | auto_increment |
| projectName | varchar(255) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

mysql> select * from emp_project_mapping;
+--------+--------+
| emp_id | pjt_id |
+--------+--------+
|      1 |      1 |
|      1 |      2 |
|      1 |      3 |
+--------+--------+
3 rows in set (0.00 sec)

mysql> select * from project;
+-----------+-------------+
| projectId | projectName |
+-----------+-------------+
|         1 | A350        |
|         2 | OLTP        |
|         3 | mobileNews  |
+-----------+-------------+
3 rows in set (0.00 sec)

mysql> select * from employee;
+----+--------------+----------+
| id | firstName    | lastName |
+----+--------------+----------+
|  1 | Hari Krishna | Gurram   |
+----+--------------+----------+
1 row in set (0.00 sec)

Prevoius                                                 Next                                                 Home

No comments:

Post a Comment