org.jdal.hibernate.HibernateUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.jdal.hibernate.HibernateUtils.java

Source

/*
 * Copyright 2008-2011 Jose Luis Martin Garcia
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jdal.hibernate;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.LockOptions;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.collection.AbstractPersistentCollection;
import org.hibernate.criterion.Example;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.Subcriteria;
import org.hibernate.impl.SessionImpl;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.collection.CollectionPersister;

/**
 * Hibernate Utility library
 *
 * @author Jose Luis Martin - (jlm@joseluismartin.info)
 */
@SuppressWarnings("rawtypes")
public abstract class HibernateUtils {

    public static final int DEFAULT_DEPTH = 2;

    private static final Log log = LogFactory.getLog(HibernateUtils.class);

    /** 
     * Initialize a Object for use whith closed session. 
     * Will recurse on properties at maximum of n depth.
     * 
     * @param sessionFactory the Hibernate SessionFactory to use
     * @param obj Object to initialize
     * @param depth max depth in recursion
     */
    public static void initialize(SessionFactory sessionFactory, Object obj, int depth) {
        initialize(sessionFactory, obj, new ArrayList<Object>(), depth);
    }

    /**
     * Initialize a Object for use with closed sessions, 
     * Use with care, will recurse on all properties.
     * 
     * @param sessionFactory the hibernate SessionFactory
     * @param obj persistent object to initialize
     */
    public static void initialize(SessionFactory sessionFactory, Object obj) {
        initialize(sessionFactory, obj, new ArrayList<Object>(), DEFAULT_DEPTH);
    }

    /** 
     * Initialize Object for use with closed Session. 
     * 
     * @param sessionFactory max depth in recursion
     * @param obj Object to initialize
     * @param initializedObjects list with already initialized Objects
     * @param depth max depth in recursion
     */
    private static void initialize(SessionFactory sessionFactory, Object obj, List<Object> initializedObjects,
            int depth) {

        // return on nulls, depth = 0 or already initialized objects
        if (obj == null || depth == 0) {
            return;
        }

        if (!Hibernate.isInitialized(obj)) {
            // if collection, initialize objects in collection too. Hibernate don't do it.
            if (obj instanceof Collection) {
                initializeCollection(sessionFactory, obj, initializedObjects, depth);
                return;
            }

            sessionFactory.getCurrentSession().buildLockRequest(LockOptions.NONE).lock(obj);
            Hibernate.initialize(obj);
        }

        // now we can call equals safely. If object are already initializated, return
        if (initializedObjects.contains(obj))
            return;

        initializedObjects.add(obj);

        // initialize all persistent associaciations.
        ClassMetadata classMetadata = getClassMetadata(sessionFactory, obj);

        if (classMetadata == null) {
            return; // Not persistent object
        }

        Object[] pvs = classMetadata.getPropertyValues(obj, EntityMode.POJO);

        for (Object pv : pvs) {
            initialize(sessionFactory, pv, initializedObjects, depth - 1);
        }
    }

    /**
     * Initalize Collection and recurse on elements 
     * 
     * @param sessionFactory the hibernate SessionFactory
     * @param obj the obj to initilize
     * @param initializedObjects list with already initialized objects
     * @param depth max depth in recursion
     */
    private static void initializeCollection(SessionFactory sessionFactory, Object obj,
            List<Object> initializedObjects, int depth) {

        Collection<?> collection = (Collection<?>) obj;
        initializeCollection(collection, sessionFactory.getCurrentSession());

        // Initialize elements
        for (Object o : collection) {
            initialize(sessionFactory, o, initializedObjects, depth - 1);
        }
    }

    /**
     * Initialize Collection (detached or not)
     * @param collection collection to initialize
     * @param session Session to use for initialization
     */
    public static void initializeCollection(Collection collection, Session session) {
        if (collection instanceof AbstractPersistentCollection) {
            AbstractPersistentCollection ps = (AbstractPersistentCollection) collection;
            log.debug("Initalizing PersistentCollection of role: " + ps.getRole());
            if (!ps.wasInitialized()) {
                SessionImpl source = (SessionImpl) session;
                PersistenceContext context = source.getPersistenceContext();
                CollectionPersister cp = source.getFactory().getCollectionPersister(ps.getRole());

                if (context.getCollectionEntry(ps) == null) { // detached
                    context.addUninitializedDetachedCollection(cp, ps);
                }

                ps.setCurrentSession(context.getSession());
                Hibernate.initialize(collection);
            }
        }
    }

    /**
     * Get ClassMetadata for persistent object
     *  
     * @param sessionFactory the hibernate SessionFactory
     * @param obj Object to initilize
     * @return ClassMetadata the class metadata
     */
    private static ClassMetadata getClassMetadata(SessionFactory sessionFactory, Object obj) {
        return sessionFactory.getClassMetadata(Hibernate.getClass(obj));
    }

    /**
     * Gets the identifier property name of persistent object
     * 
     * @param sessionFactory the hibernate SessionFactory
     * @param obj the persistent object
     * @return the identifier property name
     */
    public static String getIdentifierPropertyName(SessionFactory sessionFactory, Object obj) {

        ClassMetadata cm = getClassMetadata(sessionFactory, obj);

        return cm == null ? null : cm.getIdentifierPropertyName();

    }

    /**
     * Get all name attributes from a object that are of the given class 
     * @param obj Object to get fields
     * @param type type of the class to find.
     * @return    name attributes with the class type specified
     */
    public static Set<String> getFieldNamesByType(Object obj, Class<?> type) {
        Set<String> fieldNames = new HashSet<String>(0);
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (type.equals(field.getType())) {
                fieldNames.add(field.getName());
            }
        }
        return fieldNames;
    }

    /**
     * Get a hibernate Example object that excludes zeroes values and excludes
     * all boolean -primitive and wrapper class- attributes of a given object.  
     * @param instance given object for a build a Example object.
     * @return a hibernate Example object.
     */
    public static Example excludeBooleanFields(Object instance) {
        Example result = Example.create(instance).excludeZeroes();
        Set<String> fieldNames = getFieldNamesByType(instance, Boolean.class);
        fieldNames.addAll(getFieldNamesByType(instance, Boolean.TYPE));
        for (String fieldName : fieldNames) {
            result.excludeProperty(fieldName);
        }
        return result;
    }

    /**
     * Return a existing alias for propertyPath on Criteria or null if none
     * @param criteria Hibernate Criteria
     * @param propertyPath the property path
     * @return alias or null if none
     */
    public static String findAliasForPropertyPath(Criteria criteria, String propertyPath) {
        CriteriaImpl c = (CriteriaImpl) criteria;
        Iterator iter = c.iterateSubcriteria();
        while (iter.hasNext()) {
            Subcriteria subCriteria = (Subcriteria) iter.next();
            if (propertyPath.equals(subCriteria.getPath()))
                ;
            return subCriteria.getAlias();
        }
        // not found
        return null;
    }
}