Hello folks.
In this post we are going to discuss about Hibernate OneToMany bidirectional relationship mapping using annotations metadata.

In general all we know any an artist can have many albums. Lets consider this use case and try to implement Hibernate OneToMany bidirectional relationship.

We have a simple pojo java class which represents an Artist.

package com.gaction.domains;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
import java.util.Set;


@Entity
@Table(name = "artists")
public class Artist implements Serializable {

    private Integer id;

    private String firstName;

    private String lastName;

    private Set<Album> albums;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "artist")
    public Set<Album> getAlbums() {
        return albums;
    }

    public void setAlbums(Set<Album> albums) {
        this.albums = albums;
    }

    @Id
    @Column(name = "artist_id")
    public Integer getId() {
        return id;
    }

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

    @Column(name = "first_name")
    public String getFirstName() {
        return firstName;
    }

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

    @Column(name = "last_name")
    public String getLastName() {
        return lastName;
    }

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

As we are aware of general annotations such as @Id, @Column, @Entity, i will not dig into these annotations so i will explain @OneToMany annotation a brief description.

 private Set<Album> albums;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "artist")
    public Set<Album> getAlbums() {
        return albums;
    }

We have set of Album objects and we have @OneToMany annotation on getter method which has following attributes.
1. cascade = CascadeType.ALL – Talks about cascading.
2. fetch = FetchType.LAZY – Talks about do not fetch or load of albums from database when you are trying to load an artist record from database. Hibernate will query to database to get artist table records only.
3. mappedBy = ‘artist‘ means that albums are mapped by a property called artist which is in the other class(Albums).The entity in this side is the of the relationship, and the owner resides in the “other” entity.

We have a simple pojo java class which represents an Album.

package com.gaction.domains;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.*;

@Entity
@Table(name= "albums")
public class Album implements Serializable {
	private static final long serialVersionUID = 1L;

	private int id;
	private String name;
	private Artist artist;

	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="artist_id")
	public Artist getArtist() {
		return artist;
	}

	public void setArtist(Artist artist) {
		this.artist = artist;
	}

	@Id
	@Column(name="album_id")
	public int getId() {
		return id;
	}

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

	@Column(name="album_name")
	public String getName() {
		return name;
	}

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

		 	@Override
			public String toString() {
				return "Album [id=" + id + ", name=" + name + "]";
			}
	        	
}

As we are aware of general annotations such as @Id, @Column, @Entity, i will consider a @ManyToOne and @JoinColumn annotation candidate for brief description.

private Artist artist;

	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="artist_id")
	public Artist getArtist() {
		return artist;
	}

@ManyToOne(fetch=FetchType.LAZY) Annotation describe these albums belongs to an artist.
@JoinColumn(name=”artist_id”) Annotation describe these albums belongs to an artist. The table (albums) which represents this class has 1 extra column name ‘artist_id‘ which make sure each album record is associated to artist by using the ‘artist_id‘.It is foreign key refers to ‘artists‘ table.

Lets see a table, records and fetching queries fired by hibernate.
1. artists
+———–+————+———–+
| artist_id | first_name | last_name |
+———–+————+———–+
| 1 Jay Sean
+———–+————+———–+

-> We have simple 3 columns with artist_id as a primary key.

2.albums
+———-+————+———–+
| album_id | album_name | artist_id |
+———-+————+———–+
| 1 Ride It 1
| 2 Down 1
+———-+————+———–+

-> Along with 2 columns we have 3rd column which represents relationship between both tables.

TestClass

public class Test {
    public static void main(String[] args) {
        Configuration cfg=new Configuration().configure("hibernate.cfg.xml");
        @SuppressWarnings("deprecation")
        SessionFactory sessionFactory=cfg.buildSessionFactory();
        Session session=sessionFactory.openSession();

        Artist artist =(Artist) session.load(Artist.class,new Integer(1));
   1.     System.out.println("******************Artist******************"+artist);
   2.     System.out.println("******************Albums**************"+artist.getAlbums());
      
        session.close();
        sessionFactory.close();

    }
}

If we comment line number 2 and run the application then hibernate will query for artist object data from database. and here is query

select artist_id , first_name , last_name  from artists whereartist_id=?

but as soon as we start using albums objects hibernate again query to database for albums data and here is query

Hibernate: select artist_id , albums0_.album_id as album_id1_0_0_, albums0_.album_id as album_id1_0_1_, albums0_.artist_id as artist_i3_0_1_, albums0_.album_name as album_na2_0_1_ from albums albums0_ where albums0_.artist_id=?

This behavior is because we already mentioned on annotation ‘fetch=FetchType.LAZY‘.

Hope this help.