0
Sponsored Links


Ad by Google
In our previous post we have seen Hibernate Batch Insertion Example and in this post we are going to show you one of the popular fetching strategy called Join Fetch.

To improve the performance of queries Hibernate provides the fetching strategies, total four different types of fetching strategies supported by hibernate and those are listed below. But in this post we are going to see the implementation of Join Fetch.

Fetching strategies supported by Hibernate:
  1. Join fetching
  2. Select fetching
  3. Subselect fetching
  4. Batch fetching
In Join Fetch, Hibernate retrieves the associated instance or collection in the same SELECT, using an OUTER JOIN. So exactly one select query will executed in Join Fetch.

Lets see an example, In our Author and Book One-to-Many-Association example we have inserted few records into the database now lets fetch them from the database. We are going to fetch the number of books is associated with a particular author.

Here is an One-To-Many association mapping of an author and book table ER diagram:

Tools and Technologies we are using here:

  • JDK 7
  • Hibernate 4.3.7
  • MySql 5.1.10
  • Eclipse Juno 4.2
  • Maven 3.2

Main Objects of this project are:
  • pom.xml
  • hibernate.cfg.xml
  • annotated pojo
  • database
Step 1. Create database script.

CREATE DATABASE /*!32312 IF NOT EXISTS*/`hibernate_tutorial`;

USE `hibernate_tutorial`;

/*Table structure for table `author` */

DROP TABLE IF EXISTS `author`;

CREATE TABLE `author` (
  `author_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  `dob` datetime DEFAULT NULL,
  PRIMARY KEY (`author_id`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;

/*Table structure for table `book` */

DROP TABLE IF EXISTS `book`;

CREATE TABLE `book` (
  `book_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `isbn` varchar(255) DEFAULT NULL,
  `author_id` bigint(20) NOT NULL,
  PRIMARY KEY (`book_id`),
  KEY `FK_4sac2ubmnqva85r8bk8fxdvbf` (`author_id`),
  CONSTRAINT `FK_4sac2ubmnqva85r8bk8fxdvbf` FOREIGN KEY (`author_id`) REFERENCES `author` (`author_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=latin1;

Step 2. Create a Maven Project:
Step A: Go to File->New->Other..


Step B: Select Maven Project from the select wizard.


Step C: Select project name and location from New Maven Project wizard.


Step D: Configure project, provide GroupId, artifactId etc. See the details from the screenshot. This screen shot is from our previous post so here you need to change the artifactId something like Fetch-Join-Example and also change the group id.


Step E: After completion of all the above steps, now your project will looks like this screenshot.

3. Add project dependencies into pom.xml file:
Double click on your project's pom.xml file it will looks like this with very limited information.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.javamakeuse.fetchjoin</groupId>
  <artifactId>Fetch-Join-Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Fetch-Join-Example</name>
  
</project>

Now add hibernate and mysql dependencies entry inside pom.xml file. Paste the below code inside the project tag of pom.xml file.
<dependencies>
  <!-- Hibernate Dependency -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.7.Final</version>
  </dependency>
  
  <!-- MySql Connector dependency -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.10</version>
  </dependency>

 </dependencies>

Here is a complete pom.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.javamakeuse.fetchjoin</groupId>
  <artifactId>Fetch-Join-Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Fetch-Join-Example</name>
  
  <dependencies>
  <!-- Hibernate Dependency -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.7.Final</version>
  </dependency>
  
  <!-- MySql Connector dependency -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.10</version>
  </dependency>

 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
     <source>1.7</source>
     <target>1.7</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

4. Create a hibernate.cfg.xml file:
Create hibernate.cfg.xml file inside src/main/resources folder.

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>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernate_tutorial</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
         
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
    <property name="hbm2ddl.auto">update</property>
        <mapping class="com.javamakeuse.fetchjoin.pojo.Author"/>
        <mapping class="com.javamakeuse.fetchjoin.pojo.Book"/>
          
    </session-factory>
</hibernate-configuration>

Step 5. Create an Author annotated class:
package com.javamakeuse.fetchjoin.pojo;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

@Entity
@Table(name="author")
public class Author {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="author_id", unique=true, nullable=false)
 private long authorId;
 
 @Column(name="first_name")
 private String firstName;
 
 @Column(name="last_name")
 private String lastName;
 
 @Temporal(TemporalType.DATE)
 @Column(name="dob")
 private Date dateOfBirth;
 
 @OneToMany(mappedBy="author",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
 @Fetch(FetchMode.JOIN)
 private Set<Book> books = new HashSet<>();
 
 public long getAuthorId() {
  return authorId;
 }
 public void setAuthorId(long authorId) {
  this.authorId = authorId;
 }
 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;
 }
 public Date getDateOfBirth() {
  return dateOfBirth;
 }
 public void setDateOfBirth(Date dateOfBirth) {
  this.dateOfBirth = dateOfBirth;
 }
 public Set<Book> getBooks() {
  return books;
 }
 public void setBooks(Set<Book> books) {
  this.books = books;
 }
 
}

Note: In Author.java class we have used @Fetch(FetchMode.JOIN).

Step 6. Create a Book annotated class
package com.javamakeuse.fetchjoin.pojo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="book")
public class Book {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="book_id", unique=true, nullable=false)
 private long bookId;
 
 @Column(name="title")
 private String title;
 
 @Column(name = "isbn")
 private String isbn;
 
 @ManyToOne
 @JoinColumn(name = "author_id", nullable=false)
 private Author author;
 
 public long getBookId() {
  return bookId;
 }
 public void setBookId(long bookId) {
  this.bookId = bookId;
 }
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getIsbn() {
  return isbn;
 }
 public void setIsbn(String isbn) {
  this.isbn = isbn;
 }
 public Author getAuthor() {
  return author;
 }
 public void setAuthor(Author author) {
  this.author = author;
 }

}

Step 7. Create a HibernateUtility class: HibernateUtility class to build SessionFactory via loading Configuration file.

HibernateUtility .java
package com.javamakeuse.fetchjoin.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtility {
  private static final SessionFactory sessionFactory = buildSessionFactory();
     private static SessionFactory buildSessionFactory() {
     
      Configuration configuration = new Configuration();
      configuration.configure();

      ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().
      applySettings(configuration.getProperties()).buildServiceRegistry();
      SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
   return sessionFactory;
     }
   
     public static SessionFactory getSessionFactory() {
         return sessionFactory;
     }
}

Step 8. Create an AuthorDAO class: to perform insert/update/get/delete records into the database.
package com.javamakeuse.fetchjoin.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.javamakeuse.fetchjoin.pojo.Author;
import com.javamakeuse.fetchjoin.util.HibernateUtility;

public class AuthorDAO {
 private static SessionFactory sessionFactory;
 static {
  sessionFactory = HibernateUtility.getSessionFactory();
 }

 public static Author findById(long id) {
  Session session = sessionFactory.openSession();
  Author author = (Author) session.get(Author.class, id);

  return author;
 }

 public static Author save(Author author) {
  Session session = sessionFactory.openSession();

  session.beginTransaction();

  session.save(author);

  session.getTransaction().commit();

  return author;
 }
 
 public static Author update(Author author) {
  Session session = sessionFactory.openSession();

  session.beginTransaction();

  session.merge(author);

  session.getTransaction().commit();

  return author;

 }

 public static void delete(Author author) {
  Session session = sessionFactory.openSession();

  session.beginTransaction();

  session.delete(author);

  session.getTransaction().commit();

 }
}

Step 9. Create an AuthorService class: to call the methods of AuthorDAO class.

package com.javamakeuse.fetchjoin.service;

import java.util.Set;

import com.javamakeuse.fetchjoin.dao.AuthorDAO;
import com.javamakeuse.fetchjoin.pojo.Author;
import com.javamakeuse.fetchjoin.pojo.Book;

public class AuthorService {

 public static void main(String[] args) {
  Author author = AuthorDAO.findById(1);
  Set<Book> books = author.getBooks();
  System.out.println("Number of associated books = " + books.size());
 }
}

That's, run AuthorService class it will execute only and only one select statement with outer join, to fetch the all associated entities.

OUT PUT:
Hibernate: 
    select
        author0_.author_id as author_i1_0_0_,
        author0_.dob as dob2_0_0_,
        author0_.first_name as first_na3_0_0_,
        author0_.last_name as last_nam4_0_0_,
        books1_.author_id as author_i4_0_1_,
        books1_.book_id as book_id1_1_1_,
        books1_.book_id as book_id1_1_2_,
        books1_.author_id as author_i4_1_2_,
        books1_.isbn as isbn2_1_2_,
        books1_.title as title3_1_2_ 
    from
        author author0_ 
    left outer join
        book books1_ 
            on author0_.author_id=books1_.author_id 
    where
        author0_.author_id=?
Number of associated books = 3

Download the complete example from here Source Code


References:
Reference 1
Reference 2
Sponsored Links

0 comments:

Post a Comment