Thursday, December 1, 2011

Singleton and serialization

What is singleton?

In Java ,we can create objects by calling constructor.But imagine a scenario where we want to 
control object instantiation.There could be many reasons why we want to control the object creation.
Normally in 3 tier architecture we create single instance of service and DAO objects since we don't want to create multiple DAO objects as number of database connections are limited and by creating multiple DAO objectswe donot want to exhaust database connections.
This is just one example ,there could be multiple such examples in real world.

Code snippet for a singleton class

Here I am using double check mechanism for creating a singleton instance.

package com.kunaal.algo;

import java.io.Serializable;

/**
 * Here we are making ConnectionFactory as a singleton.
 * Since we want connection factory to be initiated once and used
 * by different classes of the project.
 * 
 * We also want to read the connection parameters once and use it as
 * a place holder for pooled connections.
 * 
 * @author KunaalATrehan
 *
 */
public class ConnectionFactory implements Serializable{
 //Static variable for holding singleton reference object
 private static ConnectionFactory INSTANCE;
 
 /**
  * Private constructor
  */
 private ConnectionFactory(){  
 }
 
 /**
  * Static method for fetching the instance
  * @return
  */
 public static ConnectionFactory getInstance(){
  //Check whether instance is null or not
  if(INSTANCE ==null){
   //Locking the class object
   synchronized(ConnectionFactory.class){
    //Doing double check for the instance
    //This is required in case first time two threads simultaneously invoke 
    //getInstance().So when another thread get the lock,it should not create the 
    //object again as its already created by the previous thread.
    if(INSTANCE==null)
     INSTANCE=new ConnectionFactory();
   }   
  }
  
  return INSTANCE;
 }
}

What happens when we serialize the singleton?

Serialization allows storing the object in some data store and re create it later on.However when we serialize a singleton class and invoke deserialization multiple times.We can end up with multiple objects of the singleton class.Even though constructor is private,deserialization process gets hold of the private constructor while recreating the object from the serialized data store.

So can we avoid it.Yes we can avoid it.We will go through step by step and explain what needs to be done when we reconstruct the object from the serialized data store so that singleton behavior is not broken when object reconstruction happens.

Case-1: Serialization breaking singleton behavior

Here we are serializing the singleton instance and reading it multiple times.So we will see that INSTANCE reference is same,however multiple objects are created.


package com.kunaal.algo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * @author KunaalATrehan
 *
 */
public class SerializationTest {

 /**
  * @param args
  * @throws IOException 
  * @throws FileNotFoundException 
  * @throws ClassNotFoundException 
  */
 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
  ConnectionFactory INSTANCE=ConnectionFactory.getInstance();
  
  //Here I am serializing the connection factory instance
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("connFactory.ser"));  
        oos.writeObject(INSTANCE);  
        oos.close();  
        
        //Here I am recreating the instance by reading the serialized object data store
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("connFactory.ser"));  
        ConnectionFactory factory1 = (ConnectionFactory) ois.readObject();  
        ois.close();  
        
        //I am recreating the instance AGAIN by reading the serialized object data store
        ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream("connFactory.ser"));  
        ConnectionFactory factory2 = (ConnectionFactory) ois2.readObject();  
        ois2.close();
        
        //Lets see how we have broken the singleton behavior
        
        System.out.println("Instance reference check->" +factory1.getInstance());
        System.out.println("Instance reference check->" +factory2.getInstance());
        System.out.println("=========================================================");
        System.out.println("Object reference check->"+factory1);
        System.out.println("Object reference check->"+factory2);
 }

}

Output is as follows:-


Instance reference check->com.kunaal.algo.ConnectionFactory@763f5d
Instance reference check->com.kunaal.algo.ConnectionFactory@763f5d
=========================================================
Object reference check->com.kunaal.algo.ConnectionFactory@13a317a
Object reference check->com.kunaal.algo.ConnectionFactory@186768e

So it has created two objects and one static reference for INSTANCE.So that means if we read the serialized format of singleton object multiple times,we will create multiple objects.This is not what singleton object is supposed to do.So can we avoid it,Yes we can.We will discuss the same in the next use case.

Case-2: Serialization and singleton working properly

In order to make serialization and singleton work properly,we have to introduce readResolve() method in the singleton class.readResolve() method lets developer control what object should be returned  on deserialization.
For the current ConnectionFactory singleton class,readResolve() method will look like this.
       /**
  * Special hook provided by serialization where developer can control what object needs to sent.
  * However this method is invoked on the new object instance created by de serialization process.
  * @return
  * @throws ObjectStreamException
  */
 private Object readResolve() throws ObjectStreamException{
  return INSTANCE;
 }

Output  is as follows:-

Instance reference check->com.kunaal.algo.ConnectionFactory@13a317a
Instance reference check->com.kunaal.algo.ConnectionFactory@13a317a
=========================================================
Object reference check->com.kunaal.algo.ConnectionFactory@13a317a
Object reference check->com.kunaal.algo.ConnectionFactory@13a317a

So now serialization and singleton is working properly and it does not matter how many times we read the serialized format of singleton object.We will get the one instance.readResolve() did the trick

Friday, November 18, 2011

Maven basics

Birth of maven

Before ANT came into place,developers used to compile java classes through command line  and generate the corresponding jar/war.It was error prone and lengthy process.


Then ANT came into picture.Developers used to write build script and use ANT to generate the required artifacts.However developer still need to write or customize the build script.Every project had a different structure ,roughly same build process with files spread over directories spread over source code.Different targets were created for cleaning the build directories,compiling the source code,running the test script,creating the deployment artifacts like war,ear,jar ,....
Developer used to worry about the dependent libraries and other stuff.



Then MAVEN was born.It standardized the project structure for most types of projects.Automated common activities like clean,compile,package and others.Relieved developers of fixing the dependencies of direct or indirect libraries.It removed inconsistent setup across developers and made process simple and transparent.

What all maven do?


Maven is a build and project management tool.

It is a build tool because of following reasons.These are:-
i) It has normalized and standardized the project structure

ii) Dependencies of third party libraries are handled gracefully.Developer need not have to download the jars and push it in the class path for building.Developer defines that this project is dependent on these tools/libraries in the pom.xml and maven does the magic of downloading  the associated jars,building the class path and managing the versions for different dependencies.

iii)We can generate the required artifacts from the project like war,jar,...Since maven has standardized the project structure.It knows which files needs to be compiled,how properties and other configuration files needs to packaged and generate the project artifact.Developer has to just fire the required goal.

iv)Lets suppose you are working in distributed environment where changes made in one module affects other module.So using mvn package will deploy the application in local /shared repository  from where others can define it as a dependency and latest changed jar file will be available to others.

v) Using various plugins we can do lots of other activities eg.plugin for jetty helps you run the war file and others.

It is a project management tool because of following reasons.These are:-
i) We can integrate integration tool like cruise control and other such tools with maven.So when any code is committed,cruise control process will run.

ii) We can integrate Bugzilla with maven.

iii)We can generate java docs,unit test reports,code coverage,code analysis using mvn site.The project site generation goal creates a professional web site of your project, including links to syntax highlighted source code, code metrics, javadoc, unit test results, and more.

Foundation blocks of maven

Maven consists of two repositories.These are :-


i) Archetype repository
Archetype repository contains information about different project types.When we invoke mvn archetype:generate.It list down the projects that we want to create.
Depending upon the selection maven creates the standardized directory structure containing folders for configuration files,source code,test cases and other required setup.

ii) Dependency repository
Most of the project depends upon third party libraries and these libraries depends upon other libraries.Different versions have different version dependencies.Maven helps in dependency management.By defining dependency of the project on third party library and corresponding version ,maven will automatically download the mentioned dependency and all other libraries which this version of dependency require.

These two are foundation blocks of the maven.

Archetype,ArtifactId,GroupId and Version

Lets take the example of creating a web based  application in java.
A web based application  needs WEB-INF,web.xml ,source folder ,test cases folder.

So what needs to be done and how maven assists us in making such application.Lets go through step by step .
1. After installing maven ,go to the directory where you want project to be setup.
Lets say we created a folder named 'DummyWebApp' under C: drive.

2. Go to C:\DummyWebApp.

3.Type mvn  archetype:generate

4.It will show you the list of project types present in maven archetype repository.So archetype is nothing but a standardized template of a project with some defaults.

5.For web based application we will enter 1 when prompt for 'Chose a number or apply filter' comes.

6.Then it  will prompt for 'Choose version:' i.e which version of archetype template you want to choose.It would have shown you the different versions available for the archetype you have selected.Go ahead with the default one.

7.Then it will prompt for ' Define a value for property <groupId>'.groupId refers to the structure in which you want to package your project in local repository or remote repository.
Eg. 
Lets suppose your code jar file is required by other dependent projects.So if you construct your jar file as ABC.jar and define groupId as com.kunaal.deploy.Then if you invoke mvn install.It will put ABC.jar inside com\kunaal\deploy folder of your local repository.

8.Then it will prompt for 'Define a value for property <artifactId>'.ArtifactId refers to name of your packaged file i.e name of the jar or war file which your project will create.
Eg.
If we give artifactId as 'Kunaal' so when we do mvn package and project is web based application and packaging strategy is 'war'.It will create Kunaal.war.

9.Then it will prompt for 'Define a value for property <version>'.Define a version

10.Then it will prompt for 'Define a value for property <package>'.i.e how you want the package structure.Normally groupId and package property is kept same.
Now you are done.It will create a directory structure like this 
DummyWebApp
                      -------> pom.xml
                      -------->src
                                           --->main
                                                         -----> java
                                                         -----> test
                                                        ------> webapp
                                                                              ------> WEB-INF ---->web.xml
                                                                              ------> index.jsp
                                                         ------> resources

So you can see by simply following the instructions.We can create a standardized project with defaults .



What is dependency and how to inform maven about it?

Every project need some third party libraries.These libraries acts as a dependency in maven.Some dependencies are required for running test cases, some are required for compiling,some are standardized service level interfaces whose implementation is provided by the server like servlet api and others.So in order to define these dependencies in pom.xml .We add a dependency tag .

Lets take an example.
Our application is dependent upon log4j and Junit.We need log4j for logging.So instead of downloading the same and publishing it in classpath.We will add dependency for the same in pom.xml.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.16</version>
</dependency>
 
So in our repository there would be folder named <groupId>\<artifactId>\<version>
Inside this there would be pom file for the same and corresponding library file.In this case there would be a folder like ...\.m2\log4j\log4j\1.2.16\log4j.jar

Similarly for JUnit,dependency would be like this.
<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
</dependency>

There is one difference here.Scope of junit dependency is 'test'.By default scope of dependency is 'compile'.Following scopes are available for dependencies.These are:-

i)Compile-This is the default scope.It means that these libraries are available at the compile time.These libraries are available in classpath of the project.

ii)Test-This means that these libraries are available during compilation and execution of test cases.

iii)Provided-This means that these libraries are provided by the container or the jdk.eg servlet

iv)Runtime-This means that these libraries are available at the runtime.

Common goals of maven
Following are the common goals of the maven.These are :-
i) validate - This checks whether project structure is proper or not and all necessary information is available or not.

ii) compile - This compiles the source code

iii)test - This runs the test cases

iv)package - This takes the compiled code and distribute it in the suitable format like jar,war

v)install -This installs the package in the local repository so that other local projects can use it.

vi) deploy- This copies the package in the remote repository.Normally done during release phase of the project.

When we invoke any goal through maven,all previous goals in the hierarchy will also run.
eg. We invoke mvn install
It will run validate,compile,test,package and install.


Settings.xml

Maven execution settings are defined in settings.xml.It contains information about the local repository,whether maven should interact with user for their input or not,whether it should work in offline mode or not.

It also states the information regarding repositories,servers and other profile related information.This file is available at following two places.These are:-
  • The Maven install: $M2_HOME/conf/settings.xml
  • A user's install: ${user.home}/.m2/settings.xml
 First one is called Global setting.Second one is called user settings.If both are present then these gets merged with user settings taking the major role.




Wednesday, September 28, 2011

Information about Mock and Stub

One of the common questions in interview,have you written test cases for your Java Code.If your code uses some other class,how you resolved this dependency.
Have you used Stubs or Mocks and whats the reason behind it?
Is there any difference between them?

Lets discuss this scenario and figure out when to use what.
Use Case
We have to create authentication module in our system.It checks for username and password and returns true or false depending upon whether username and password supplied is correct
or not.In our use case we have a LoginService which uses IUserDAO.There is a concrete class named UserDAO which implements IUserDAO and uses database table for doing authentication check.It will return success/failure as authentication result

So now if we have to write test case for LoginService authenticate () method.We need to provide some implementation for IUserDAO for test case to complete.We fake the IUserDAO  implementation by creating a mock or stub of it.

What is Stub?

Stub is a fake implementation of the dependent class.If we follow interface driven approach we can create a stub by implementing the interface and provide hard coded return values.
The basic idea is to implement the dependencies as concrete classes, which reveal only a small part of the overall behavior of the dependent class, which is needed by the class under test.

+ves
-There is no dependency on external jars.
-We are writing extra class having redundant implementation and hard coded return values for testing our api.
-Easy to simulate and understand

-ves
-If interface changes we have to modify the stubs.
-There could be multiple stub implementations for testing different  api's because if we use one stub class for all test case,we may break other test cases.
-If interface has many methods our stub will have lots of empty methods.

Above use case with Stub Implementation

 
package com.kunaal.stubMock.test;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import com.kunaal.stubMock.dao.IUserDAO;
import com.kunaal.stubMock.service.LoginService;

/**
 * @author Kunaal A Trehan
 *
 */
public class LoginServiceTest {
	
	private LoginService loginService=new LoginService();
	
	/**
	 * Here we setting stub implementation for userDAO which we will use in this service
	 * So interface driven approach helps us to fake the dependency by injecting  
	 * stub[anonymous implementation of IUserDAO] of other class and let us test 
	 * our method  
	 */
	@Before
	public void stubSetup(){
		loginService.setUserDAO(new IUserDAO(){

			public boolean authenticate(String uName, String passWd) {
				if(uName!=null && uName.equals("Kunaal") && 
						passWd !=null && passWd.equals("Password"))
					return true;
				else
					return false;
			}
		});
	}
	
	
	@Test
	public void authenticate(){
		assertTrue(loginService.authenticate("Kunaal", "Password"));
		assertFalse(loginService.authenticate("Kunaal", "Kunaal"));
	}

}


What is Mock?


Mock also fake's the implementation .But in case of mock we record and verify the interaction between the two classes.Basic idea is to plug the expectation at the runtime and verify the same.

+ves

-No need to create an extra class for faking the implementation
-Relives us from having blank implementations for methods in case number of methods are huge.
-We can define the expectation at the run time
-We can verify whether the method in the dependent class has actually been invoked or not

-ves
-Need third party api for providing mocking behavior
-Its not straight forward to understand

Above use case with mock implementation

package com.kunaal.stubMock.test;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import com.kunaal.stubMock.dao.UserDAO;
import com.kunaal.stubMock.service.LoginService;

/**
 * @author Kunaal A Trehan
 *
 */
public class MockLoginServiceTest {
	
	private LoginService loginService;
	private UserDAO mockUserDAO;
	
	@Before
	public void setup(){
		loginService=new LoginService();
		mockUserDAO=createMock(UserDAO.class);
		loginService.setUserDAO(mockUserDAO);
	}
	
	@Test
	public void authenticate(){
		//push the expectations and other information
		// Set expectations on mocks.
		expect(mockUserDAO.authenticate("Kunaal","Password")).
			andReturn(true);
		// Set mocks into testing mode.
		replay(mockUserDAO);
		
		assertTrue(loginService.authenticate("Kunaal", "Password"));
		//assertFalse(loginService.authenticate("Kunaal", "Kunaal"));
		verify(mockUserDAO);
	}


}

Whats the difference between these two?
So final word whats the difference between these two.As per my understanding mock is generated at the run time and it helps to test the state as well as interaction behavior between two classes.This is not possible in stub implementation as there is no way to verify whether the particular method in the dependent class has been invoked by the test class or not.


However I can be wrong.Do let me know if my understanding is not right.

Wednesday, August 31, 2011

N+1 and fetch strategies in hibernate

What is N+1 problem in Hibernate?
Lets take a use case of Library.One Library can have any number of books.Imagine a screen where we are listing library information and book details.

By default hibernate fetches the associated objects lazily.That means associated collection is not fetched.Instead hibernate creates a proxy for the same.There will be proxy for every object of the collection.

So when hibernate fetches the library information.Hibernate will fire following queries.These are:-
i) One query to fetch the parent object which is Library in this case and initializing the associated collection with proxy for each item in the collection which is books in this case.
ii)N queries for hydrating/fetching the data for the proxy of associated item in the collection.
So for fetching the data we are firing N+1 queries.

Are there any solutions to this problem.Can we avoid it?
We can avoid it by tweaking batch size and fetch mode which is explained below.

Batch Size 
When we define batch size for the many valued collection.Hibernate fetches child records for the size mentioned by batch size property.

i.e If we have a data set of 5 libraries.Each having N number of books. and we provide batch size as 3.Then when do listing of all libraries.It will eagerly fetch book data for 3 libraries .so instead of 5+1 queries.It will fire 1+1(Fetch book data for 3 libraries)+1(fetch book data for remaining 2 libraries)

Sub Select strategy
When we use sub select strategy for fetch mode.Then hibernate fetches child records for all entities of the parent node.It actually fires query with IN clause while selecting child records.


i.e Taking the above example.Lets suppose we are selecting data on the basis of some condition which returns 4 libraries.If we have incorporated sub select strategy.Then hibernate will fetch book data for all the 4 libraries.

In order to understand better lets take a use case

UseCase:- Every project has set of QA people,Dev people, and works on a particular technology stack.So a project has one to many relationship with QA ,Dev team and technology stack.

SQL Script:-
create table ORM_SW_Project(
	ProjectId bigint Identity(1,1) primary key,
	ProjectName varchar(50) not null,
	ProjectManager varchar(100) not null
)

create table ORM_SW_QA(
    QAId bigint Identity(1,1) primary key,
    QAName varchar(100) not null,
    QAAge int not null,
    ProjectId bigint not null
)

create table ORM_SW_Dev(
    DevId bigint identity(1,1) primary key,
    DevName varchar(100) not null,
    DevAge int not null,
    ProjectId bigint not null
)

create table ORM_SW_Tech(
    TechId bigint identity(1,1) primary key,
    TechName varchar(100) not null,
    TechVersion varchar(50) not null,
    ProjectId bigint not null
)

alter table ORM_SW_QA 
add  FOREIGN KEY (ProjectId) REFERENCES ORM_SW_Project(ProjectId);

alter table ORM_SW_Dev 
add  FOREIGN KEY (ProjectId) REFERENCES ORM_SW_Project(ProjectId);

alter table ORM_SW_Tech 
add  FOREIGN KEY (ProjectId) REFERENCES ORM_SW_Project(ProjectId);

insert into ORM_SW_Project(ProjectName,ProjectManager)values('New Website','Mr.X');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project1','Mr.Y1');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project2','Mr.Y2');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project3','Mr.Y3');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project4','Mr.Y4');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project5','Mr.Y5');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project6','Mr.Y6');
insert into ORM_SW_Project(ProjectName,ProjectManager)values('Integration Project7','Mr.Y7');

insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Sidney',34,1);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Rama',40,1);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Shiva',28,1);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Hary',35,1);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Avril',29,1);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Nancy',30,1);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('James',34,2);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Tommy',29,2);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('James',25,2);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Michael',29,2);

insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Sidney3',34,3);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Rama3',40,3);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Shiva3',28,3);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Hary3',35,3);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Avril3',29,3);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Nancy3',30,3);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('James4',34,4);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Tommy4',29,4);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('James4',25,4);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Michael4',29,4);

insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Sidney5',34,5);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Rama5',40,5);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Shiva5',28,5);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Hary5',35,5);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Avril5',29,5);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Nancy5',30,5);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('James6',34,6);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Tommy6',29,6);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('James6',25,6);
insert into ORM_SW_QA(QAName,QAAge,ProjectId)values('Michael6',29,6);


insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Kunaal',33,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Pavan',30,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Nitish',35,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Arvind',30,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Pankaj',28,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Mamu',29,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Preet',32,1);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Mohan',38,2);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Deepak',37,2);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Kanak',29,2);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Rashmi',34,2);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Jeril',30,2);

insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Kunaal3',33,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Pavan3',30,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Nitish3',35,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Arvind3',30,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Pankaj3',28,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Mamu3',29,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Preet3',32,3);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Mohan4',38,4);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Deepak4',37,4);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Kanak4',29,4);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Rashmi4',34,4);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Jeril4',30,4);

insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Kunaal5',33,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Pavan5',30,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Nitish5',35,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Arvind5',30,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Pankaj5',28,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Mamu5',29,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Preet5',32,5);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Mohan6',38,6);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Deepak6',37,6);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Kanak6',29,6);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Rashmi6',34,6);
insert into ORM_SW_Dev(DevName,DevAge,ProjectId)values('Jeril6',30,6);

insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Java','1.6',1);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Spring','3.0',1);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Hibernate','3.5',1);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Restful Webservices','1.2',1);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Oracle','9.0',1);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('.Net','2.0',2);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Oracle','9.0',2);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Restful Webservices','1.2',2);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Oracle','1.2',8);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Restful Webservices','1.2',8);
insert into ORM_SW_Tech(TechName,TechVersion,ProjectId) values('Java','1.2',8);

Java Model Classes

SWProject.java having one to many relationship with QA,Dev, and Technology
package com.kunaal.model.fetchMode;

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

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

import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
import org.hibernate.annotations.FetchProfile.FetchOverride;
import org.hibernate.annotations.FetchProfiles;

import com.kunaal.model.BaseModel;

/**
 * @author Kunaal A Trehan
 * 
 */
@Entity
@Table(name="ORM_SW_Project")
public class SWProject implements BaseModel<Long>{

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="ProjectId")
	private Long projId;
	
	@Column(name="ProjectName")
	private String projName;
	
	@Column(name="ProjectManager")
	private String projMgr;
	
	@OneToMany(cascade=CascadeType.ALL,mappedBy="project")
//	@BatchSize(size=5)
	@Fetch(FetchMode.SUBSELECT)
	private Set<SWQA> qaSet=new HashSet<SWQA>();
	
	@OneToMany(cascade=CascadeType.ALL,mappedBy="project")
//	@BatchSize(size=5)
	private Set<SWDev> devSet=new HashSet<SWDev>();
	
	@OneToMany(cascade=CascadeType.ALL,mappedBy="project")
//	@BatchSize(size=5)
	private Set<SWTech> techSet=new HashSet<SWTech>();
	
	public Long getPrimaryKey() {
		return getProjId();
	}

	/**
	 * @return the projId
	 */
	public Long getProjId() {
		return projId;
	}

	/**
	 * @param projId the projId to set
	 */
	public void setProjId(Long projId) {
		this.projId = projId;
	}

	/**
	 * @return the projName
	 */
	public String getProjName() {
		return projName;
	}

	/**
	 * @param projName the projName to set
	 */
	public void setProjName(String projName) {
		this.projName = projName;
	}

	/**
	 * @return the projMgr
	 */
	public String getProjMgr() {
		return projMgr;
	}

	/**
	 * @param projMgr the projMgr to set
	 */
	public void setProjMgr(String projMgr) {
		this.projMgr = projMgr;
	}

	/**
	 * @return the qaSet
	 */
	public Set<SWQA> getQaSet() {
		return qaSet;
	}

	/**
	 * @param qaSet the qaSet to set
	 */
	public void setQaSet(Set<SWQA> qaSet) {
		this.qaSet = qaSet;
	}

	/**
	 * @return the devSet
	 */
	public Set<SWDev> getDevSet() {
		return devSet;
	}

	/**
	 * @param devSet the devSet to set
	 */
	public void setDevSet(Set<SWDev> devSet) {
		this.devSet = devSet;
	}

	/**
	 * @return the techSet
	 */
	public Set<SWTech> getTechSet() {
		return techSet;
	}

	/**
	 * @param techSet the techSet to set
	 */
	public void setTechSet(Set<SWTech> techSet) {
		this.techSet = techSet;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((projId == null) ? 0 : projId.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		SWProject other = (SWProject) obj;
		if (projId == null) {
			if (other.projId != null)
				return false;
		} else if (!projId.equals(other.projId))
			return false;
		return true;
	}

}


SWDev.java showing Dev details
package com.kunaal.model.fetchMode;

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;

import com.kunaal.model.BaseModel;

/**
 * @author Kunaal A Trehan
 *
 */
@Entity
@Table(name="ORM_SW_Dev")
public class SWDev implements BaseModel<Long>{

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="DevId")
	private Long devId;
	
	@Column(name="DevName")
	private String devName;
	
	@Column(name="DevAge")
	private Integer age;
	
	@ManyToOne
	@JoinColumn(name="ProjectId")
	private SWProject project;
	
	public Long getPrimaryKey() {
		return getDevId();
	}

	/**
	 * @return the devId
	 */
	public Long getDevId() {
		return devId;
	}

	/**
	 * @param devId the devId to set
	 */
	public void setDevId(Long devId) {
		this.devId = devId;
	}

	/**
	 * @return the devName
	 */
	public String getDevName() {
		return devName;
	}

	/**
	 * @param devName the devName to set
	 */
	public void setDevName(String devName) {
		this.devName = devName;
	}

	/**
	 * @return the age
	 */
	public Integer getAge() {
		return age;
	}

	/**
	 * @param age the age to set
	 */
	public void setAge(Integer age) {
		this.age = age;
	}

	/**
	 * @return the project
	 */
	public SWProject getProject() {
		return project;
	}

	/**
	 * @param project the project to set
	 */
	public void setProject(SWProject project) {
		this.project = project;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((devId == null) ? 0 : devId.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		SWDev other = (SWDev) obj;
		if (devId == null) {
			if (other.devId != null)
				return false;
		} else if (!devId.equals(other.devId))
			return false;
		return true;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "SWDev [devId=" + devId + ", devName=" + devName + "]";
	}

}

SWQA.java showing QA details
package com.kunaal.model.fetchMode;

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;

import org.hibernate.annotations.BatchSize;

import com.kunaal.model.BaseModel;

/**
 * @author Kunaal A Trehan
 *
 */
@Entity
@Table(name="ORM_SW_QA")
//@BatchSize(size=2)
public class SWQA implements BaseModel<Long>{

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="QAId")
	private Long id;
	
	@Column(name="QAName")
	private String name;
	
	@Column(name="QAAge")
	private Integer age;
	
	@ManyToOne
	@JoinColumn(name="projectId")
	private SWProject project;
	
	public Long getPrimaryKey() {
		return getId();
	}

	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the age
	 */
	public Integer getAge() {
		return age;
	}

	/**
	 * @param age the age to set
	 */
	public void setAge(Integer age) {
		this.age = age;
	}

	/**
	 * @return the project
	 */
	public SWProject getProject() {
		return project;
	}

	/**
	 * @param project the project to set
	 */
	public void setProject(SWProject project) {
		this.project = project;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		SWQA other = (SWQA) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "SWQA [id=" + id + ", name=" + name + "]";
	}

}

SWTech.java showing technology details
package com.kunaal.model.fetchMode;

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;

import com.kunaal.model.BaseModel;

/**
 * @author Kunaal A Trehan
 *
 */
@Entity
@Table(name="ORM_SW_Tech")
public class SWTech implements BaseModel<Long>{

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="TechId")
	private Long id;
	
	@Column(name="TechName")
	private String name;
	
	@Column(name="TechVersion")
	private String version;
	
	@ManyToOne
	@JoinColumn(name="ProjectId")
	private SWProject project;
	
	public Long getPrimaryKey() {
		return getId();
	}

	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the version
	 */
	public String getVersion() {
		return version;
	}

	/**
	 * @param version the version to set
	 */
	public void setVersion(String version) {
		this.version = version;
	}

	/**
	 * @return the project
	 */
	public SWProject getProject() {
		return project;
	}

	/**
	 * @param project the project to set
	 */
	public void setProject(SWProject project) {
		this.project = project;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		SWTech other = (SWTech) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "SWTech [id=" + id + ", name=" + name + "]";
	}

}


So we have 8 projects in the database and in SWProject.java we have placed fetch mode as SUBSELECT and there is a commented entry for BatchSize(size=5).There is a test case in which we list all the projects and print the QA details.So when we have fetch mode as SUBSELECT,there will be 2 queries fired,one for project details and creating the proxy for all the associated collections and another for  hydrating the proxy for QA collection.

However when we use comment fetch mode as SUBSELECT and use BatchSize(size=5).There will be 3 queries fired,one for project details  and creating the proxy for associated collections and another 2 queries for hydrating the proxy for QA collection.Since batch size is 5 and no of projects is 8 so 2 queries will be fired.


Test Case(ProjectServiceTest.java)
package com.kunaal.service;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.FetchMode;
import org.hibernate.annotations.FetchProfile;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import com.kunaal.model.fetchMode.SWProject;

/**
 * @author Kunaal A Trehan
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-main.xml"})
@TransactionConfiguration(defaultRollback=false)
public class ProjectServiceTest  implements ApplicationContextAware {

	private ApplicationContext appCtx;
	
	@Autowired	
	private IProjectService projectService;
	
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.appCtx=applicationContext;
	}

        @Test
	@Transactional
	public void listAll(){
		List<SWProject> list = projectService.listAll();
		
		for(SWProject project:list){
			System.out.println("Project is:"+project);
			System.out.println("QA is:"+project.getQaSet());
			//System.out.println("Dev is:"+project.getDevSet());
			//System.out.println("Tech is:" +project.getTechSet());
		}
	}
}

Test execution log when @BatchSize(size=5) is enabled.If we look into highlighted italic section ,hibernate has fired 3 queries as explained earlier

Aug 31, 2011 5:19:08 PM org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
INFO: @TestExecutionListeners is not present for class [class com.kunaal.service.ProjectServiceTest]: using defaults.
Aug 31, 2011 5:19:08 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-main.xml]
Aug 31, 2011 5:19:08 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-hibernate-config.xml]
Aug 31, 2011 5:19:08 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-dao.xml]
Aug 31, 2011 5:19:08 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-service.xml]
Aug 31, 2011 5:19:08 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@1befab0: startup date [Wed Aug 31 17:19:08 GMT+05:30 2011]; root of context hierarchy
Aug 31, 2011 5:19:08 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1506dc4: defining beans [sessionFactory,interceptor,transactionManager,baseDAO,addrDAO,deptDAO,emplDAO,personDAO,flatEmpDAO,apptDAO,nriBankAcctDAO,enumPersonDAO,qualEnumDAO,publisherDAO,parentDAO,paymentDAO,singlePymtDAO,empVersionDAO,stockDAO,stateDAO,singerDAO,hqlDAO,criteriaDAO,mfDAO,mappedDAO,plainDeptDAO,plainUniDeptDAO,projectDAO,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,baseService,addrService,emplService,deptService,personService,flatEmplService,apptService,nriBankAcctService,enumPersonService,qualEnumService,publisherService,parentService,paymentService,singlePymtService,empVersionService,stockService,stateService,singerService,hqlService,criteriaService,mfService,mappedService,plainDeptService,plainUniDeptService,projectService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor]; root of factory hierarchy
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Aug 31, 2011 5:19:09 PM org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
Aug 31, 2011 5:19:11 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransactionManager@12a416a]; rollback [false]
Hibernate: select this_.ProjectId as ProjectId39_0_, this_.ProjectManager as ProjectM2_39_0_, this_.ProjectName as ProjectN3_39_0_ from ORM_SW_Project this_
Project is:com.kunaal.model.fetchMode.SWProject@20
Hibernate: select qaset0_.projectId as projectId39_1_, qaset0_.QAId as QAId1_, qaset0_.QAId as QAId40_0_, qaset0_.QAAge as QAAge40_0_, qaset0_.QAName as QAName40_0_, qaset0_.projectId as projectId40_0_ from ORM_SW_QA qaset0_ where qaset0_.projectId in (?, ?, ?, ?, ?)
QA is:[SWQA [id=3, name=Shiva], SWQA [id=1, name=Sidney], SWQA [id=5, name=Avril], SWQA [id=2, name=Rama], SWQA [id=4, name=Hary], SWQA [id=6, name=Nancy]]
Project is:com.kunaal.model.fetchMode.SWProject@21
QA is:[SWQA [id=10, name=Michael], SWQA [id=9, name=James], SWQA [id=7, name=James], SWQA [id=8, name=Tommy]]
Project is:com.kunaal.model.fetchMode.SWProject@22
QA is:[SWQA [id=14, name=Hary3], SWQA [id=16, name=Nancy3], SWQA [id=12, name=Rama3], SWQA [id=15, name=Avril3], SWQA [id=11, name=Sidney3], SWQA [id=13, name=Shiva3]]
Project is:com.kunaal.model.fetchMode.SWProject@23
QA is:[SWQA [id=20, name=Michael4], SWQA [id=19, name=James4], SWQA [id=17, name=James4], SWQA [id=18, name=Tommy4]]
Project is:com.kunaal.model.fetchMode.SWProject@24
Hibernate: select qaset0_.projectId as projectId39_1_, qaset0_.QAId as QAId1_, qaset0_.QAId as QAId40_0_, qaset0_.QAAge as QAAge40_0_, qaset0_.QAName as QAName40_0_, qaset0_.projectId as projectId40_0_ from ORM_SW_QA qaset0_ where qaset0_.projectId in (?, ?, ?)
QA is:[SWQA [id=22, name=Rama5], SWQA [id=24, name=Hary5], SWQA [id=26, name=Nancy5], SWQA [id=21, name=Sidney5], SWQA [id=25, name=Avril5], SWQA [id=23, name=Shiva5]]
Project is:com.kunaal.model.fetchMode.SWProject@25
QA is:[SWQA [id=27, name=James6], SWQA [id=29, name=James6], SWQA [id=30, name=Michael6], SWQA [id=28, name=Tommy6]]
Project is:com.kunaal.model.fetchMode.SWProject@26
QA is:[]
Project is:com.kunaal.model.fetchMode.SWProject@27
QA is:[]
Aug 31, 2011 5:19:11 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Committed transaction after test execution for test context [[TestContext@1df3d59 testClass = ProjectServiceTest, locations = array<String>['classpath:spring-main.xml'], testInstance = com.kunaal.service.ProjectServiceTest@134c5ff, testMethod = listAll@ProjectServiceTest, testException = [null]]]
Aug 31, 2011 5:19:11 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@1befab0: startup date [Wed Aug 31 17:19:08 GMT+05:30 2011]; root of context hierarchy
Aug 31, 2011 5:19:11 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1506dc4: defining beans [sessionFactory,interceptor,transactionManager,baseDAO,addrDAO,deptDAO,emplDAO,personDAO,flatEmpDAO,apptDAO,nriBankAcctDAO,enumPersonDAO,qualEnumDAO,publisherDAO,parentDAO,paymentDAO,singlePymtDAO,empVersionDAO,stockDAO,stateDAO,singerDAO,hqlDAO,criteriaDAO,mfDAO,mappedDAO,plainDeptDAO,plainUniDeptDAO,projectDAO,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,baseService,addrService,emplService,deptService,personService,flatEmplService,apptService,nriBankAcctService,enumPersonService,qualEnumService,publisherService,parentService,paymentService,singlePymtService,empVersionService,stockService,stateService,singerService,hqlService,criteriaService,mfService,mappedService,plainDeptService,plainUniDeptService,projectService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor]; root of factory hierarchy
Aug 31, 2011 5:19:11 PM org.springframework.orm.hibernate3.AbstractSessionFactoryBean destroy
INFO: Closing Hibernate SessionFactory

Test execution log when @Fetch(FetchMode.SUBSELECT) is enabled.If we look into highlighted italic section ,hibernate has fired 2 queries as explained earlier


Aug 31, 2011 5:38:05 PM org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
INFO: @TestExecutionListeners is not present for class [class com.kunaal.service.ProjectServiceTest]: using defaults.
Aug 31, 2011 5:38:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-main.xml]
Aug 31, 2011 5:38:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-hibernate-config.xml]
Aug 31, 2011 5:38:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-dao.xml]
Aug 31, 2011 5:38:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-service.xml]
Aug 31, 2011 5:38:05 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@1befab0: startup date [Wed Aug 31 17:38:05 GMT+05:30 2011]; root of context hierarchy
Aug 31, 2011 5:38:06 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1506dc4: defining beans [sessionFactory,interceptor,transactionManager,baseDAO,addrDAO,deptDAO,emplDAO,personDAO,flatEmpDAO,apptDAO,nriBankAcctDAO,enumPersonDAO,qualEnumDAO,publisherDAO,parentDAO,paymentDAO,singlePymtDAO,empVersionDAO,stockDAO,stateDAO,singerDAO,hqlDAO,criteriaDAO,mfDAO,mappedDAO,plainDeptDAO,plainUniDeptDAO,projectDAO,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,baseService,addrService,emplService,deptService,personService,flatEmplService,apptService,nriBankAcctService,enumPersonService,qualEnumService,publisherService,parentService,paymentService,singlePymtService,empVersionService,stockService,stateService,singerService,hqlService,criteriaService,mfService,mappedService,plainDeptService,plainUniDeptService,projectService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor]; root of factory hierarchy
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Aug 31, 2011 5:38:06 PM org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
Aug 31, 2011 5:38:08 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransactionManager@12cb585]; rollback [false]
Hibernate: select this_.ProjectId as ProjectId39_0_, this_.ProjectManager as ProjectM2_39_0_, this_.ProjectName as ProjectN3_39_0_ from ORM_SW_Project this_
Project is:com.kunaal.model.fetchMode.SWProject@20
Hibernate: select qaset0_.projectId as projectId39_1_, qaset0_.QAId as QAId1_, qaset0_.QAId as QAId40_0_, qaset0_.QAAge as QAAge40_0_, qaset0_.QAName as QAName40_0_, qaset0_.projectId as projectId40_0_ from ORM_SW_QA qaset0_ where qaset0_.projectId in (select this_.ProjectId from ORM_SW_Project this_)
QA is:[SWQA [id=3, name=Shiva], SWQA [id=1, name=Sidney], SWQA [id=5, name=Avril], SWQA [id=2, name=Rama], SWQA [id=4, name=Hary], SWQA [id=6, name=Nancy]]
Project is:com.kunaal.model.fetchMode.SWProject@21
QA is:[SWQA [id=10, name=Michael], SWQA [id=9, name=James], SWQA [id=7, name=James], SWQA [id=8, name=Tommy]]
Project is:com.kunaal.model.fetchMode.SWProject@22
QA is:[SWQA [id=14, name=Hary3], SWQA [id=16, name=Nancy3], SWQA [id=12, name=Rama3], SWQA [id=15, name=Avril3], SWQA [id=11, name=Sidney3], SWQA [id=13, name=Shiva3]]
Project is:com.kunaal.model.fetchMode.SWProject@23
QA is:[SWQA [id=20, name=Michael4], SWQA [id=19, name=James4], SWQA [id=17, name=James4], SWQA [id=18, name=Tommy4]]
Project is:com.kunaal.model.fetchMode.SWProject@24
QA is:[SWQA [id=22, name=Rama5], SWQA [id=24, name=Hary5], SWQA [id=26, name=Nancy5], SWQA [id=21, name=Sidney5], SWQA [id=25, name=Avril5], SWQA [id=23, name=Shiva5]]
Project is:com.kunaal.model.fetchMode.SWProject@25
QA is:[SWQA [id=27, name=James6], SWQA [id=29, name=James6], SWQA [id=30, name=Michael6], SWQA [id=28, name=Tommy6]]
Project is:com.kunaal.model.fetchMode.SWProject@26
QA is:[]
Project is:com.kunaal.model.fetchMode.SWProject@27
QA is:[]
Aug 31, 2011 5:38:08 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Committed transaction after test execution for test context [[TestContext@df824a testClass = ProjectServiceTest, locations = array<String>['classpath:spring-main.xml'], testInstance = com.kunaal.service.ProjectServiceTest@1e2c9bf, testMethod = listAll@ProjectServiceTest, testException = [null]]]
Aug 31, 2011 5:38:08 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@1befab0: startup date [Wed Aug 31 17:38:05 GMT+05:30 2011]; root of context hierarchy
Aug 31, 2011 5:38:08 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1506dc4: defining beans [sessionFactory,interceptor,transactionManager,baseDAO,addrDAO,deptDAO,emplDAO,personDAO,flatEmpDAO,apptDAO,nriBankAcctDAO,enumPersonDAO,qualEnumDAO,publisherDAO,parentDAO,paymentDAO,singlePymtDAO,empVersionDAO,stockDAO,stateDAO,singerDAO,hqlDAO,criteriaDAO,mfDAO,mappedDAO,plainDeptDAO,plainUniDeptDAO,projectDAO,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,baseService,addrService,emplService,deptService,personService,flatEmplService,apptService,nriBankAcctService,enumPersonService,qualEnumService,publisherService,parentService,paymentService,singlePymtService,empVersionService,stockService,stateService,singerService,hqlService,criteriaService,mfService,mappedService,plainDeptService,plainUniDeptService,projectService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor]; root of factory hierarchy