Home Hibernate Hibernate - many-to-many unidirectional association

Hibernate – many-to-many unidirectional association

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 :

many to many

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.

Join Table in associations in JPA and Hibernate

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

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;
 
//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;
 
    //Uni-directional many-to-many association to Subject
    @ManyToMany(cascade={CascadeType.ALL})
    @JoinTable(name="BRANCH_SUBJECT", [email protected](name="BRANCH_ID"),
    [email protected](name="SUBJECT_ID"))//@JoinTable is used to map Join table in database
    private List<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 association UniDirectional testing

/**
 * JPA Many-To-Many UniDirectional
 *
 */
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
            branch1.setSubjects(new ArrayList());
            branch1.addSubject(getSubject1());//Software Engineering
            branch1.addSubject(getSubject2());//Distributed System
            branch2.setSubjects(new ArrayList());
            branch2.addSubject(getSubject1());//Software Engineering
            branch2.addSubject(getSubject3());//Business Analysis and Optimization
            
            entityManager.persist(branch1);
            entityManager.persist(branch2);
            
            transaction.commit();
            
        }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;
    }
}

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 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 (?, ?)
INFO - HHH000030: Cleaning up connection pool [jdbc:mysql://localhost:3306/jpa_JBD]

Download Application – JPA-ManyToMany-UniDirection.zip (14 KB)

Satish Varma
Satish Varmahttps://javabydeveloper.com
Satish is post graduated in master of computer applications and experienced software engineer with focus on Spring, JPA, REST, TDD and web development. Follow him on LinkedIn or Twitter or Facebook

3 COMMENTS

  1. Hi,
    I don’t want to create a subject entry each time the entitymanager persists. I want to save a branch and joining table with existing subject Id. Could you please explain how that becomes possible?

  2. In a Branch entity, cascade is use as a CascadeType.ALL i.e. @ManyToMany(cascade={CascadeType.ALL}) . If we delete the Subject entity it would delete the Branch entity which would have referenced to another Subject entity as well so it should not have ALL cascade type, It would be Cascade.PERSIST and Cascade.Merge.

    Please correct me If I am wrong

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Stay in Touch

Categories