Hibernate Self Join Many to Many Mapping with Extra Column using Annotation

In this tutorial I will show you how to implement Self-Join Many to Many mapping with an extra column using Hibernate Annotation.

Figure 26.1 illustrates Self Reference many-to-many relationship.

Figure 26.1 Figure 26.1

According to this relationship each person can have friends and each friend is a person.

First create a new Java Project and configure it as Maven Project. For Reference, Click Here

Add the following dependencies in pom.xml

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.15</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>4.1.7.Final</version>
    </dependency>
    <dependency>
      <groupId>javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.12.1.GA</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.6</version>
    </dependency>
  </dependencies>

1. Sql Script

Use the following Sql Script for creating table.

create table Person(
    person_id int(10) primary key NOT NULL AUTO_INCREMENT,
    Name varchar(50));
  
create table friends(
    person_id int(10) NOT NULL,
    friend_id int(10) NOT NULL,
	friendship_date date,
    FOREIGN KEY (person_id) REFERENCES Person (person_id),
	FOREIGN KEY (friend_id) REFERENCES Person (person_id),
    PRIMARY KEY (person_id, friend_id));

2. Pojo

Now create Person Class as following.

Person.java

package com.kruders.bean;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Person generated by hbm2java
 */
@Entity
@Table(name = "person", catalog = "test")
public class Person implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer personId;
	private String name;
	private Set<Friends> friends = new HashSet<Friends>(0);
	private Set<Friends> persons = new HashSet<Friends>(0);

	public Person() {
	}

	public Person(String name) {
		this.name =  name;
	}
	public Person(String name, Set<Friends> friends,
			Set<Friends> persons) {
		this.name = name;
		this.friends = friends;
		this.persons = persons;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "person_id", unique = true, nullable = false)
	public Integer getPersonId() {
		return this.personId;
	}

	public void setPersonId(Integer personId) {
		this.personId = personId;
	}

	@Column(name = "Name", length = 50)
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "friends")
	public Set<Friends> getFriends() {
		return this.friends;
	}

	public void setFriends(Set<Friends> friends) {
		this.friends = friends;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "persons")
	public Set<Friends> getPersons() {
		return this.persons;
	}

	public void setPersons(Set<Friends> persons) {
		this.persons = persons;
	}

}

We have defined two attributes Set<Friends> persons and Set<Friends> friends. The persons attribute is relationship owner. @OneToMany annotation is defined on both persons and friends attributes.


Now create Friends and FriendsId Class as following.

Friends.java

package com.kruders.bean;

import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * Friends generated by hbm2java
 */
@Entity
@Table(name = "friends", catalog = "test")
public class Friends implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private FriendsId id;
	private Person friends;
	private Person persons;
	private Date friendshipDate;

	public Friends() {
	}

	public Friends(FriendsId id, Person friends,
			Person persons) {
		this.id = id;
		this.friends = friends;
		this.persons = persons;
	}

	public Friends(FriendsId id, Person friends,
			Person persons, Date friendshipDate) {
		this.id = id;
		this.friends = friends;
		this.persons = persons;
		this.friendshipDate = friendshipDate;
	}

	@EmbeddedId
	@AttributeOverrides({
			@AttributeOverride(name = "personId", column = @Column(name = "person_id", nullable = false)),
			@AttributeOverride(name = "friendId", column = @Column(name = "friend_id", nullable = false)) })
	public FriendsId getId() {
		return this.id;
	}

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

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "friend_id", nullable = false, insertable = false, updatable = false)
	public Person getFriends() {
		return this.friends;
	}

	public void setFriends(Person friends) {
		this.friends = friends;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "person_id", nullable = false, insertable = false, updatable = false)
	public Person getPersons() {
		return persons;
	}

	public void setPersons(Person persons) {
		this.persons = persons;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "friendship_date", length = 10)
	public Date getFriendshipDate() {
		return this.friendshipDate;
	}

	

	public void setFriendshipDate(Date friendshipDate) {
		this.friendshipDate = friendshipDate;
	}

}


FriendsId.java

package com.kruders.bean;

import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 * FriendsId generated by hbm2java
 */
@Embeddable
public class FriendsId implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int personId;
	private int friendId;

	public FriendsId() {
	}

	public FriendsId(int personId, int friendId) {
		this.personId = personId;
		this.friendId = friendId;
	}

	@Column(name = "person_id", nullable = false)
	public int getPersonId() {
		return this.personId;
	}

	public void setPersonId(int personId) {
		this.personId = personId;
	}

	@Column(name = "friend_id", nullable = false)
	public int getFriendId() {
		return this.friendId;
	}

	public void setFriendId(int friendId) {
		this.friendId = friendId;
	}

	public boolean equals(Object other) {
		if ((this == other))
			return true;
		if ((other == null))
			return false;
		if (!(other instanceof FriendsId))
			return false;
		FriendsId castOther = (FriendsId) other;

		return (this.getPersonId() == castOther.getPersonId())
				&& (this.getFriendId() == castOther.getFriendId());
	}

	public int hashCode() {
		int result = 17;

		result = 37 * result + this.getPersonId();
		result = 37 * result + this.getFriendId();
		return result;
	}

}

3. Hibernate Configuration File

Now create the hibernate configuration file and add all the mapping files.

hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">admin</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        
        <mapping class="com.kruders.bean.Person" />
        <mapping class="com.kruders.bean.Friends" />
    </session-factory>
</hibernate-configuration>

4. Hibernate Utility Class

Now create HibernateUtil class. The HibernateUtil class helps in creating the SessionFactory from the Hibernate configuration file. A org.hibernate.SessionFactory is used to obtain org.hibernate.Session instances. A org.hibernate.Session represents a single-threaded unit of work. The org.hibernate.SessionFactory is a thread-safe global object that is instantiated once.

package com.kruders.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
  
public class HibernateUtil {
  
    private static final SessionFactory sessionFactory = buildSessionFactory();
  
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
  
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

5. Run Program

Create Main.java class and run it as Java Application

package com.kruders.core;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.kruders.bean.Friends;
import com.kruders.bean.FriendsId;
import com.kruders.bean.Person;
import com.kruders.util.HibernateUtil;


public class Main {
	public static void main(String args[]) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			
			transaction = session.beginTransaction();
			
	        Person person1 = new Person("Puneet");
	        Person person2 = new Person("Ahsan");
	        Person person3 = new Person("Shally");
	        
        	        
	        session.save(person2);
	        session.save(person3);
	        session.save(person1);
	        FriendsId friendId1 = new FriendsId(person1.getPersonId(), person2.getPersonId());
	        Friends friend1 = new Friends();
	        friend1.setId(friendId1);
	        session.save(friend1);
	        
	        
			transaction.commit();
		}catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		
	}
	
	
}

The folder structure of the example is shown below in Figure 26.2

Figure 26.2 Figure 26.2

You can download the source code of this example here.

No comments yet.

Leave a Reply