There are times we have many to many relation between 2 objects (tables). The many to many relationship between 2 tables is defined by a third table. For example, suppose we 2 tables: “customer” and “service” and we say that a customer can be related to more than one service, we add a third table: “user_customer” that will hold the relations between customers and services.
Let’s summarize the structure of these 3 tables:
- customer: This table holds customers. The fields in this table are:
- customer_id (primary key)
- first_name
- last_name
- service: This table holds list of services that a customer can receive. For example, cables TV customer can get the following services: Sports, Drama, News etc’. A customer can get more than one service. The fields in this table are:
- service_id (primary key)
- name
- customer_service: This table defines the relation between customers and services. It connected users to services. It contains only the key from each table:
- user_id
- service_id
Note that “customer” and “service” tables used in this example doesn’t contain all the business data usually would have been used in the real world. This is to make things simpler.
Hibernate has a special annotation that helps us to define this relation: @ManyToMany. This is how this annotation is being used:
This is the Customer class representing the “customer” table:
package com.bashan.blog.hibernate;import javax.persistence.*;import java.util.Set;@Entity@Table(name = "customer")public class Customer {@Id@Column(name = "customer_id")private Integer customerId;@Column(name = "first_name")private String firstName;@Column(name = "last_name")private String lastName;@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})@JoinTable(name = "customer_service",joinColumns = {@JoinColumn(name = "customer_id")},inverseJoinColumns = @JoinColumn(name = "service_id"))private Set<Service> services;public Integer getCustomerId() {return customerId;}public void setCustomerId(Integer customerId) {this.customerId = customerId;}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;}}
This is the Service class representing the “service” table:
package com.bashan.blog.hibernate;import javax.persistence.*;import java.util.Set;@Entity@Table(name = "service")public class Service {@Id@Column(name = "service_id")private Integer serviceId;@Column(name = "name")private String name;@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})@JoinTable(name = "customer_service",joinColumns = {@JoinColumn(name = "service_id")},inverseJoinColumns = @JoinColumn(name = "customer_id"))private Set<Customer> customers;public Integer getServiceId() {return serviceId;}public void setServiceId(Integer serviceId) {this.serviceId = serviceId;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
Not that there is no need to define any CustomerService object since the @ManyToMany annotation already contains this information in the “name” property of the @JoinTable.
The code for these 2 classes can be found in this link.