0
Sponsored Links


Ad by Google
In our previous post we have seen Hibernate 4 Batch Fetching Example and in this post we are going to show you Hibernate Subselect Fetching strategy example using annotation.
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.

Fetching strategies supported by Hibernate:
  1. Join fetching
  2. Select fetching
  3. Subselect fetching
  4. Batch fetching
Subselect fetching: a second SELECT is used to retrieve the associated collections for all entities retrieved in a previous query or fetch. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you access the association. Only two select query will be executed in Subselect fetching.

Lets implement the Subselect fetching strategy to fetch all the entities with associations using @Fetch(FetchMode.SUBSELECT).

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 old post so here you need to change the artifactId something like Subselect-Fetch-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.fetch</groupId>
  <artifactId>Subselect-Fetch-Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Subselect-Fetch-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.fetch</groupId>
  <artifactId>Subselect-Fetch-Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Subselect-Fetch-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>
        <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>
         
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property> 
        <property name="hbm2ddl.auto">update</property>
        <mapping class="com.javamakeuse.fetch.pojo.Author"/>
        <mapping class="com.javamakeuse.fetch.pojo.Book"/>
          
    </session-factory>
</hibernate-configuration>

Step 5. Create an Author annotated class:
package com.javamakeuse.fetch.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.BatchSize;

@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.SUBSELECT)
 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;
 }
}

Step 6. Create a Book annotated class

package com.javamakeuse.fetch.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.fetch.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.

AuthorDAO.java
package com.javamakeuse.fetch.dao;

import java.util.List;

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

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

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

 public static List<Author> findAll() {
  Session session = sessionFactory.openSession();
  List<Author> authorList = session.createQuery("from Author").list();
  return authorList;
 }

 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.

AuthorService.java
package com.javamakeuse.fetch.service;

import java.util.List;

import com.javamakeuse.fetch.dao.AuthorDAO;
import com.javamakeuse.fetch.pojo.Author;

public class AuthorService {

 public static void main(String[] args) {
  List<Author> authorList = AuthorDAO.findAll();
  for (Author author : authorList) {
   author.getBooks().size();
  }

 }
}

Run AuthorService and see the out put it will create two select statements one for fetch all the authors and one for fetch all the associated books with sub select query.
OUT PUT:
Hibernate: 
    select
        author0_.author_id as author_i1_0_,
        author0_.dob as dob2_0_,
        author0_.first_name as first_na3_0_,
        author0_.last_name as last_nam4_0_ 
    from
        author author0_
Hibernate: 
    select
        books0_.author_id as author_i4_0_1_,
        books0_.book_id as book_id1_1_1_,
        books0_.book_id as book_id1_1_0_,
        books0_.author_id as author_i4_1_0_,
        books0_.isbn as isbn2_1_0_,
        books0_.title as title3_1_0_ 
    from
        book books0_ 
    where
        books0_.author_id in (
            select
                author0_.author_id 
            from
                author author0_
        )


That's it :)

Download the complete example from here Source Code


References:
Reference 1
Reference 2

Sponsored Links

0 comments:

Post a Comment