many-to-many bidirectional mapping :
In a relational database in a many-to-many relationship, a row in table X can have more than one matching row in table Y, a row in table Y can have more than one matching row in table X.
In Object oriented programming, one instance of entity refers to multiple instances of another entity and an instance of that another entity refers to multiple instances of the other entity in the relation called many-to-many relation.
In this tutorial used the relationship between Engineering Branch and Subjects that are having each Engineering branch in a semester. In an Engineering college each Branch have many Subjects and each Subject may appear in many Engineering branch semester.
many-to-many Tables structure in Database :
what is join table?
A join table is a table in database that represents the multiple references of one or more table . In other words a join table is used to refer multiple records of one or more tables by using foreign key constraints. Below image illustrates more about many-to-many association.
Technologies Used in following example :
- JPA 2.1
- Hibernate 5.2.6
- MySql 8.0
- Maven 3
- Spring Tool Suite (STS) 3.9.8
- Java 1.8
what is bidirectional?
- Bidirectional relationship provides navigational access in both directions, so that you can access the other side entity without explicit queries.
Subject.java mapping :
/** * The persistent class for the Subject database table. * */ @Entity public class Subject implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "native") @GenericGenerator(name = "native", strategy = "native") @Column(name="SUBJECT_ID") private int subjectId; @Column(name="SUBJECT_DESC") private String subjectDesc; @Column(name="SUBJECT_NAME") private String subjectName; //bi-directional many-to-many association to Branch @ManyToMany(mappedBy="subjects",cascade = CascadeType.ALL) private Set<Branch> branches = new HashSet<Branch>(); //Setters and getters }
Branch.java mapping :
/** * The persistent class for the BRANCH database table. * */ @Entity public class Branch implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "native") @GenericGenerator(name = "native", strategy = "native") @Column(name="BRANCH_ID") private int branchId; @Column(name="BRANCH_NAME") private String branchName; @Column(name="BRANCH_SHORT_NAME") private String branchShortName; private String description; //bi-directional many-to-many association to Subject @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name="BRANCH_SUBJECT" , joinColumns={ @JoinColumn(name="BRANCH_ID") } , inverseJoinColumns={ @JoinColumn(name="SUBJECT_ID") } ) private Set<Subject> subjects; //Setters and getters }
@JoinTable
- @JoinTable Used in the mapping of associations. It is specified on the owning side of an association.
- @JoinTable can be used with embeddable types as well.When a join table is used in mapping a relationship with an embeddable class on the owning side of the relationship, the containing entity rather than the embeddable class is considered the owner of the relationship.
To Understand more about @JoinTable mapping in entity associations see :
Key points to understand associations
many-to-many bidirectional mapping testing :
/** * JPA Many-To-Many BiDirectional * */ public class App { public static void main( String[] args ) { EntityManagerFactory emf = null; EntityManager entityManager = null; EntityTransaction transaction = null; try{ emf = Persistence.createEntityManagerFactory("jbd-pu"); entityManager = emf.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Branch branch1 = getBranch1();//CSE Branch in Engineering Branch branch2 = getBranch2();//IT Branch in Engineering Subject subject1 = getSubject1(); Subject subject2 = getSubject2(); Subject subject3 = getSubject3(); branch1.setSubjects(new HashSet<Subject>()); branch1.addSubject(subject1);//Software Engineering branch1.addSubject(subject2);//Distributed System branch2.setSubjects(new HashSet<Subject>()); branch2.addSubject(subject1);//Software Engineering branch2.addSubject(subject3);//Business Analysis and Optimization subject1.addBranch(branch1); subject1.addBranch(branch2); subject2.addBranch(branch1); subject3.addBranch(branch2); entityManager.persist(branch1); entityManager.persist(branch2); transaction.commit(); Subject retrievedSubject = entityManager.find(Subject.class, new ArrayList<Subject>(branch1.getSubjects()).get(0).getSubjectId()); for(Branch retrivedBranch : retrievedSubject.getBranches()){ System.err.println("Branch "+new ArrayList<Branch>(retrievedSubject.getBranches()).indexOf(retrivedBranch)+" : "); System.err.println(retrivedBranch.getBranchName()); } }catch(Exception e){ transaction.rollback(); e.printStackTrace(); }finally{ entityManager.close(); emf.close(); } } private static Subject getSubject1(){ Subject subject = new Subject(); subject.setSubjectName("Software Engineering"); subject.setSubjectDesc("Apply key aspects of software engineering processes for the development of a complex software system"); return subject; } private static Subject getSubject2(){ Subject subject = new Subject(); subject.setSubjectName("Distributed System"); subject.setSubjectDesc("Explore recent advances in distributed computing systems"); return subject; } private static Subject getSubject3(){ Subject subject = new Subject(); subject.setSubjectName("Business Analysis and Optimization"); subject.setSubjectDesc("understand the Internal and external factors that impact the business strategy"); return subject; } private static Branch getBranch1(){ Branch branch = new Branch(); branch.setBranchName("Computer Science and Engineering"); branch.setBranchShortName("CSE"); branch.setDescription("CSE department offers courses under ambitious curricula in computer science and computer engineering.."); return branch; } private static Branch getBranch2(){ Branch branch = new Branch(); branch.setBranchName("Information Technology"); branch.setBranchShortName("IT"); branch.setDescription("IT is the business side of computers - usually dealing with databases, business, and accounting"); return branch; } }
Console output :
INFO - HHH000400: Using dialect: org.hibernate.dialect.MySQLInnoDBDialect INFO - HHH000397: Using ASTQueryTranslatorFactory Hibernate: insert into Branch (BRANCH_NAME, BRANCH_SHORT_NAME, description) values (?, ?, ?) Hibernate: insert into Subject (SUBJECT_DESC, SUBJECT_NAME) values (?, ?) Hibernate: insert into Branch (BRANCH_NAME, BRANCH_SHORT_NAME, description) values (?, ?, ?) Hibernate: insert into Subject (SUBJECT_DESC, SUBJECT_NAME) values (?, ?) Hibernate: insert into Subject (SUBJECT_DESC, SUBJECT_NAME) values (?, ?) Hibernate: insert into BRANCH_SUBJECT (BRANCH_ID, SUBJECT_ID) values (?, ?) Hibernate: insert into BRANCH_SUBJECT (BRANCH_ID, SUBJECT_ID) values (?, ?) Hibernate: insert into BRANCH_SUBJECT (BRANCH_ID, SUBJECT_ID) values (?, ?) Hibernate: insert into BRANCH_SUBJECT (BRANCH_ID, SUBJECT_ID) values (?, ?) Branch 0 : Computer Science and Engineering Branch 1 : Information Technology
Download Application – JPA-ManyToMany-BiDirection.zip (16 KB)