Below is the code attached with appropriate comments:
package reflection;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
/**
* @author SacrosanctBlood
*
*
* <p>
* This utility class is used to execute an hibernate query on a single entity class, with any number of conditions
* (equals conditions only, but can be extended)on the attributes of the class. It also fetches the Objects given in the
* list which would otherwise be fetched lazily.
* </p>
*/
public class HibernateQueryUtil {
/**
* This method returns the result of the find query on the given input class.
*
* @param session
* The hibernate session in which the query will be executed. This can not be null.
* @param clazz
* The entity class which is mapped to a table in database, on which the query is executed. This can not
* be null.
* @param conditions
* A map of attributeName = attributeValue for the attributes in the class. These represents the
* conditions for the fetch query. This can be null.
* @param fetchList
* A list of attributes in the class representing a foreign relationship that needs to be fetched
* eagerly. This can be null.
* @return List A list of the resultant Objects of the type clazz which have been eagerly initialized according to
* the fetchList. The List can be empty dependent on the query executed.
* @throws IllegalArgumentException
* Thrown when
* <li>Clazz is not valid</li>
* <li>Attributes are not present in clazz</li>
* <li>Attributes in fetchList is not valid.</li>
*/
public static List find(Session session, Class clazz, Map<String, Object> conditions, List<String> fetchList)
throws IllegalArgumentException {
Set<String> attributes = null;
attributes = initializeAttributes(conditions);
String entityName = clazz.getSimpleName();
List result = null;
if (entityName != null) {
Criteria criteria = session.createCriteria(clazz);
if (conditions != null) {
checkIfAttributesExistInClass(clazz, attributes);
addCriterions(criteria, conditions, attributes);
}
result = executeQuery(criteria);
if (fetchList != null && result != null) {
checkIfAttributesExistInClass(clazz, fetchList);
List<String> methodsToInvoke = convertFetchListToMethodToInvokeList(fetchList);
checkIfMethodsExistInClass(clazz, methodsToInvoke);
initializeFetchList(clazz, methodsToInvoke, result);
}
} else {
throw new IllegalArgumentException("Class " + clazz.getName() + " is not valid");
}
return result;
}
/**
* This method eagerly initializes each of the attributes for each Object in the resultList.
*
* @param clazz
* @param methodsToInvoke
* @param resultlist
* @throws IllegalArgumentException
*/
private static void initializeFetchList(Class clazz, List<String> methodsToInvoke, List resultlist)
throws IllegalArgumentException {
// called methods have no argument(They are just getter methods)
Class params[] = {};
Object paramsObj[] = {};
for (Object resultObject : resultlist) {
if (clazz.isInstance(resultObject)) {
for (String aMethod : methodsToInvoke) {
try {
// get the method
Method thisMethod = clazz.getDeclaredMethod(aMethod, params);
// invoke the method on the object and initiliaze in Hibernate
Hibernate.initialize(thisMethod.invoke(resultObject, paramsObj).toString());
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException(
"Error while invoking method to initiliaze in HibernateQueryUtil:initilizeFetchList");
}
}
} else {
throw new IllegalArgumentException(
"The resultant Objects of the hibernate query are not the same as the Class "
+ clazz.getSimpleName());
}
}
}
/**
* This method checks if the methodToInvoke is present in the given Class.
*
* @param clazz
* @param methodsToInvoke
* @throws IllegalArgumentException
*/
private static void checkIfMethodsExistInClass(Class clazz, Collection<String> methodsToInvoke)
throws IllegalArgumentException {
for (String thisMethod : methodsToInvoke) {
try {
clazz.getDeclaredMethod(thisMethod);
} catch (SecurityException e) {
throw new IllegalArgumentException("Method with name " + thisMethod + " is not accessible");
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Method with name " + thisMethod + " does not exist");
}
}
}
/**
* This method converts the fetchList which is just a list of attributes in class, to the corresponding getter
* method on the attribute. This method is later invoked in <i>initializeFetchList</i>.
*
* @param fetchList
* @return List A list containing methods to be invoked.
*/
private static List<String> convertFetchListToMethodToInvokeList(List<String> fetchList) {
List<String> convertedList = new ArrayList<String>();
for (String thisAttribute : fetchList) {
String firstLetterInUpperCase = String.valueOf(thisAttribute.charAt(0)).toUpperCase();
String getterMethodString = "get" + firstLetterInUpperCase + thisAttribute.substring(1);
convertedList.add(getterMethodString);
}
return convertedList;
}
/**
* This method returns a Set of the attributes present in the Class given as an input to <i>find</i> method.
*
* @param attributes
* @return Set All the attributes.
*/
private static Set<String> initializeAttributes(Map<String, Object> attributes) {
Set<String> keys = null;
if (attributes != null)
keys = attributes.keySet();
return keys;
}
/**
*
* @param clazz
* @param attributes
* @throws IllegalArgumentException
*/
private static void checkIfAttributesExistInClass(Class clazz, Collection<String> attributes)
throws IllegalArgumentException {
for (String thisAttribute : attributes) {
try {
clazz.getDeclaredField(thisAttribute);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException("Column with name " + thisAttribute + " does not exist");
}
}
}
/**
* This method add new criterions for the criteria object.
*
* @param criteria
* @param columns
* @param keys
*/
private static void addCriterions(Criteria criteria, Map<String, Object> columns, Collection<String> keys) {
for (String thisAttribute : keys) {
Object thisAttributValue = columns.get(thisAttribute);
// equals operator by default
criteria.add(Expression.eq(thisAttribute, thisAttributValue));
}
}
/**
*
* @param criteria
* @return List Result of executing the query
*/
private static List executeQuery(Criteria criteria) {
List result = null;
if (criteria != null) {
result = criteria.list();
}
return result;
}
}
Below is a client that uses this utility class:
package client;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import entity.data.Data;
import entity.datachildren.DataChildren;
import reflection.HibernateQueryUtil;
public class Client {
public static void main(String[] args) throws Exception{
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
//case 1: get all the Data.
List list = HibernateQueryUtil.find(session, Data.class, null,null);
Iterator iter = list.iterator();
while(iter.hasNext()){
Data data = (Data)iter.next();
}
//case 2: get Data with dataId = 3 and dataBy = "ABC"
Map<String, Object> conditions = new HashMap<String, Object>();
map.put("dataId", new Integer(3));
conditions.put("dataBy", "ABC");
// also fetch Data Childrens
List<String> fetchList = new ArrayList<String>();
fetchList.add("dataChildrens");
// list = HibernateQueryUtil.find(session, Data.class, map,null); throws LazyInitializeException
list = HibernateQueryUtil.find(session, Data.class, conditions,fetchList);//initializes so no problem
session.close();
Set ds = null;
iter = list.iterator();
while(iter.hasNext()){
Data data = (Data)iter.next();
System.out.println(data.getDataId() + " " + data.getDataBy());
ds = data.getDataChildrens();
Iterator dIter = ds.iterator();
while(dIter.hasNext()){
System.out.println("LP: " + ((DataChildren)dIter.next()).getDataChildrenName());
}
}
}
}
Hope this was helpful..