org.beangle.orm.hibernate.HibernateEntityDao.java Source code

Java tutorial

Introduction

Here is the source code for org.beangle.orm.hibernate.HibernateEntityDao.java

Source

/*
 * Beangle, Agile Java/Scala Development Scaffold and Toolkit
 *
 * Copyright (c) 2005-2013, Beangle Software.
 *
 * Beangle is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Beangle is distributed in the hope that it will be useful.
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Beangle.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.beangle.orm.hibernate;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.Clob;
import java.util.*;

import org.beangle.commons.collection.CollectUtils;
import org.beangle.commons.collection.page.Page;
import org.beangle.commons.collection.page.PageLimit;
import org.beangle.commons.collection.page.SinglePage;
import org.beangle.commons.dao.EntityDao;
import org.beangle.commons.dao.Operation;
import org.beangle.commons.dao.query.LimitQuery;
import org.beangle.commons.dao.query.QueryBuilder;
import org.beangle.commons.dao.query.builder.Condition;
import org.beangle.commons.dao.query.builder.OqlBuilder;
import org.beangle.commons.entity.Entity;
import org.beangle.commons.entity.metadata.ModelMeta;
import org.beangle.commons.lang.Arrays;
import org.beangle.commons.lang.Assert;
import org.beangle.commons.lang.Strings;
import org.beangle.orm.hibernate.internal.SessionHolder;
import org.beangle.orm.hibernate.internal.SessionUtils;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.StreamUtils;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author chaostone
 */
public class HibernateEntityDao implements EntityDao {

    /** Logger available to subclasses */
    protected Logger logger = LoggerFactory.getLogger(getClass());

    protected SessionFactory sessionFactory;

    protected ModelMeta modelMeta;

    protected Session getSession() {
        SessionHolder holder = SessionUtils.currentSession(sessionFactory);
        return null != holder ? holder.getSession() : null;
    }

    @SuppressWarnings({ "unchecked" })
    public <T extends Entity<ID>, ID extends Serializable> T get(Class<T> clazz, ID id) {
        return (T) get(modelMeta.getEntityType(clazz).getEntityName(), id);
    }

    @SuppressWarnings({ "unchecked" })
    public <T> T get(String entityName, Serializable id) {
        if (Strings.contains(entityName, '.')) {
            return (T) getSession().get(entityName, id);
        } else {
            String hql = "from " + entityName + " where id =:id";
            Query query = getSession().createQuery(hql);
            query.setParameter("id", id);
            List<?> rs = query.list();
            if (rs.isEmpty()) {
                return null;
            } else {
                return (T) rs.get(0);
            }
        }
    }

    @SuppressWarnings("unchecked")
    public <T extends Entity<?>> List<T> getAll(Class<T> clazz) {
        String hql = "from " + modelMeta.getEntityType(clazz).getEntityName();
        Query query = getSession().createQuery(hql);
        query.setCacheable(true);
        return query.list();
    }

    public <T extends Entity<ID>, ID extends Serializable> List<T> get(Class<T> clazz, ID[] values) {
        return get(clazz, "id", (Object[]) values);
    }

    public <T extends Entity<ID>, ID extends Serializable> List<T> get(Class<T> clazz, Collection<ID> values) {
        return get(clazz, "id", values.toArray());
    }

    public <T extends Entity<?>> List<T> get(Class<T> entityClass, String keyName, Object... values) {
        if (entityClass == null || Strings.isEmpty(keyName) || values == null || values.length == 0) {
            return Collections.emptyList();
        }
        String entityName = modelMeta.getEntityType(entityClass).getEntityName();
        return get(entityName, keyName, values);
    }

    public <T extends Entity<?>> List<T> get(Class<T> clazz, String keyName, Collection<?> values) {
        if (clazz == null || Strings.isEmpty(keyName) || values == null || values.isEmpty()) {
            return Collections.emptyList();
        }
        String entityName = modelMeta.getEntityType(clazz).getEntityName();
        return get(entityName, keyName, values.toArray());
    }

    public <T> List<T> get(String entityName, String keyName, Object... values) {
        StringBuilder hql = new StringBuilder();
        hql.append("select entity from ").append(entityName).append(" as entity where entity.").append(keyName)
                .append(" in (:keyName)");
        Map<String, Object> parameterMap = CollectUtils.newHashMap();
        if (values.length < 500) {
            parameterMap.put("keyName", values);
            QueryBuilder<T> query = OqlBuilder.hql(hql.toString());
            return search(query.params(parameterMap).build());
        } else {
            QueryBuilder<T> query = OqlBuilder.hql(hql.toString());
            List<T> rs = CollectUtils.newArrayList();
            int i = 0;
            while (i < values.length) {
                int end = i + 500;
                if (end > values.length)
                    end = values.length;
                parameterMap.put("keyName", Arrays.subarray(values, i, end));
                rs.addAll(search(query.params(parameterMap).build()));
                i += 500;
            }
            return rs;
        }
    }

    public <T extends Entity<?>> List<T> get(Class<T> clazz, String[] attrs, Object... values) {
        Map<String, Object> params = CollectUtils.newHashMap();
        for (int i = 0; i < attrs.length; i++) {
            params.put(attrs[i], values[i]);
        }
        return get(clazz, params);
    }

    /**
     * @param clazz
     * @param parameterMap
     * @return data list
     */
    public <T extends Entity<?>> List<T> get(Class<T> clazz, final Map<String, Object> parameterMap) {
        if (clazz == null || parameterMap == null || parameterMap.isEmpty()) {
            return Collections.emptyList();
        }
        String entityName = clazz.getName();
        StringBuilder hql = new StringBuilder();
        hql.append("select entity from ").append(entityName).append(" as entity ").append(" where ");

        Map<String, Object> m = new HashMap<String, Object>(parameterMap.keySet().size());
        // ???
        int i = 0;
        for (final String keyName : parameterMap.keySet()) {
            if (Strings.isEmpty(keyName)) {
                return null;
            }
            i++;
            Object keyValue = parameterMap.get(keyName);

            String[] tempName = Strings.split(keyName, "\\.");
            String name = tempName[tempName.length - 1] + i;
            m.put(name, keyValue);

            if (keyValue != null && (keyValue.getClass().isArray() || keyValue instanceof Collection<?>)) {
                hql.append("entity.").append(keyName).append(" in (:").append(name).append(") and ");
            } else {
                hql.append("entity.").append(keyName).append(" = :").append(name).append(" and ");
            }
        }
        if (i > 0)
            hql.delete(hql.length() - " and ".length(), hql.length());
        return search(hql.toString(), m);
    }

    /**
     * ???
     * 
     * @see #buildCountQueryStr(Query)
     * @see org.beangle.commons.collection.page.Page
     */
    public <T> List<T> search(org.beangle.commons.dao.query.Query<T> query) {
        if (query instanceof LimitQuery) {
            org.beangle.commons.dao.query.LimitQuery<T> limitQuery = (org.beangle.commons.dao.query.LimitQuery<T>) query;
            if (null == limitQuery.getLimit()) {
                return QuerySupport.find(limitQuery, getSession());
            } else {
                return new SinglePage<T>(limitQuery.getLimit().getPageNo(), limitQuery.getLimit().getPageSize(),
                        QuerySupport.count(limitQuery, getSession()), QuerySupport.find(query, getSession()));
            }
        } else {
            return QuerySupport.find(query, getSession());
        }
    }

    /**
     * hql?
     * 
     * @param <T>
     * @param builder
     * @return data list
     */
    public <T> List<T> search(QueryBuilder<T> builder) {
        return (List<T>) search(builder.build());
    }

    @SuppressWarnings("unchecked")
    public <T> T uniqueResult(QueryBuilder<T> builder) {
        List<?> list = search(builder.build());
        if (list.isEmpty()) {
            return null;
        } else if (list.size() == 1) {
            return (T) list.get(0);
        } else {
            throw new RuntimeException("not unique query" + builder);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> search(String query, Object... params) {
        return (List<T>) QuerySupport.setParameter(getNamedOrCreateQuery(query), params).list();
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> search(String queryString, Map<String, Object> params) {
        return QuerySupport.setParameter(getNamedOrCreateQuery(queryString), params).list();
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> search(String queryString, final Map<String, Object> params, PageLimit limit,
            boolean cacheable) {
        Query query = getNamedOrCreateQuery(queryString);
        query.setCacheable(cacheable);
        if (null == limit)
            return QuerySupport.setParameter(query, params).list();
        else
            return paginateQuery(query, params, limit);
    }

    /**
     * Support "@named-query" or "from object" styles query
     * 
     * @param queryString
     * @return Hibernate query
     */
    private Query getNamedOrCreateQuery(String queryString) {
        if (queryString.charAt(0) == '@')
            return getSession().getNamedQuery(queryString.substring(1));
        else
            return getSession().createQuery(queryString);
    }

    public void evict(Object entity) {
        getSession().evict(entity);
    }

    public int executeUpdate(final String queryString, final Object... argument) {
        return QuerySupport.setParameter(getNamedOrCreateQuery(queryString), argument).executeUpdate();
    }

    public int[] executeUpdateRepeatly(final String queryString, final Collection<Object[]> arguments) {
        Query query = getNamedOrCreateQuery(queryString);
        int[] updates = new int[arguments.size()];
        int i = 0;
        for (Object[] params : arguments) {
            updates[i] = QuerySupport.setParameter(query, params).executeUpdate();
            i++;
        }
        return updates;
    }

    public int executeUpdate(final String queryString, final Map<String, Object> parameterMap) {
        return QuerySupport.setParameter(getNamedOrCreateQuery(queryString), parameterMap).executeUpdate();
    }

    public Blob createBlob(InputStream inputStream, int length) {
        return Hibernate.getLobCreator(getSession()).createBlob(inputStream, length);
    }

    public Blob createBlob(InputStream inputStream) {
        try {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream(inputStream.available());
            StreamUtils.copy(inputStream, buffer);
            return Hibernate.getLobCreator(getSession()).createBlob(buffer.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Clob createClob(String str) {
        return Hibernate.getLobCreator(getSession()).createClob(str);
    }

    public void refresh(Object entity) {
        getSession().refresh(entity);
    }

    @SuppressWarnings("unchecked")
    public <T> T initialize(T proxy) {
        if (proxy instanceof HibernateProxy) {
            LazyInitializer init = ((HibernateProxy) proxy).getHibernateLazyInitializer();
            if (null == init.getSession() || init.getSession().isClosed()) {
                proxy = (T) getSession().get(init.getEntityName(), init.getIdentifier());
            } else {
                Hibernate.initialize(proxy);
            }
        } else if (proxy instanceof PersistentCollection) {
            Hibernate.initialize(proxy);
        }
        return proxy;
    }

    /**
     * @param query
     * @param params
     * @param limit
     * @return a page data
     */
    @SuppressWarnings("unchecked")
    private <T> Page<T> paginateQuery(Query query, Map<String, Object> params, PageLimit limit) {
        QuerySupport.setParameter(query, params);
        query.setFirstResult((limit.getPageNo() - 1) * limit.getPageSize()).setMaxResults(limit.getPageSize());
        List<T> targetList = query.list();
        String queryStr = buildCountQueryStr(query);
        Query countQuery = null;
        if (query instanceof SQLQuery) {
            countQuery = getSession().createSQLQuery(queryStr);
        } else {
            countQuery = getSession().createQuery(queryStr);
        }
        QuerySupport.setParameter(countQuery, params);
        // 
        return new SinglePage<T>(limit.getPageNo(), limit.getPageSize(),
                ((Number) (countQuery.uniqueResult())).intValue(), targetList);
    }

    public void saveOrUpdate(Object... entities) {
        if (null == entities)
            return;
        for (Object entity : entities) {
            if (entity instanceof Collection<?>) {
                for (Object elementEntry : (Collection<?>) entity) {
                    persistEntity(elementEntry, null);
                }
            } else {
                persistEntity(entity, null);
            }
        }
    }

    public void save(Object... entities) {
        if (null == entities)
            return;
        for (Object entity : entities) {
            if (entity instanceof Collection<?>) {
                for (Object elementEntry : (Collection<?>) entity) {
                    saveEntity(elementEntry, null);
                }
            } else {
                saveEntity(entity, null);
            }
        }
    }

    public void execute(Operation... opts) {
        for (Operation operation : opts) {
            switch (operation.type) {
            case SAVE_UPDATE:
                persistEntity(operation.data, null);
                break;
            case REMOVE:
                remove(operation.data);
                break;
            }
        }
    }

    public void execute(Operation.Builder builder) {
        for (Operation operation : builder.build()) {
            switch (operation.type) {
            case SAVE_UPDATE:
                persistEntity(operation.data, null);
                break;
            case REMOVE:
                remove(operation.data);
                break;
            }
        }
    }

    public void saveOrUpdate(Collection<?> entities) {
        if (null != entities && !entities.isEmpty()) {
            for (Object entity : entities) {
                persistEntity(entity, null);
            }
        }
    }

    private void saveEntity(Object entity, String entityName) {
        if (null == entity)
            return;
        if (null != entityName) {
            getSession().save(entityName, entity);
        } else {
            if (entity instanceof HibernateProxy) {
                getSession().save(entity);
            } else {
                getSession().save(modelMeta.getEntityType(entity.getClass()).getEntityName(), entity);
            }
        }
    }

    private void persistEntity(Object entity, String entityName) {
        if (null == entity)
            return;
        if (null != entityName) {
            getSession().saveOrUpdate(entityName, entity);
        } else {
            if (entity instanceof HibernateProxy) {
                getSession().saveOrUpdate(entity);
            } else {
                getSession().saveOrUpdate(modelMeta.getEntityType(entity.getClass()).getEntityName(), entity);
            }
        }
    }

    public void saveOrUpdate(String entityName, Collection<?> entities) {
        if (null != entities && !entities.isEmpty()) {
            for (Object entity : entities) {
                persistEntity(entity, entityName);
            }
        }
    }

    public void saveOrUpdate(String entityName, Object... entities) {
        if (null == entities)
            return;
        for (Object entity : entities) {
            persistEntity(entity, entityName);
        }
    }

    public int update(Class<?> entityClass, String attr, Object[] values, String[] argumentName,
            Object[] argumentValue) {
        if (null == values || values.length == 0) {
            return 0;
        }
        Map<String, Object> updateParams = CollectUtils.newHashMap();
        for (int i = 0; i < argumentValue.length; i++) {
            updateParams.put(argumentName[i], argumentValue[i]);
        }
        return update(entityClass, attr, values, updateParams);

    }

    public int update(Class<?> entityClass, String attr, Object[] values, Map<String, Object> updateParams) {
        if (null == values || values.length == 0 || updateParams.isEmpty()) {
            return 0;
        }
        String entityName = entityClass.getName();
        StringBuilder hql = new StringBuilder();
        hql.append("update ").append(entityName).append(" set ");
        Map<String, Object> newParams = CollectUtils.newHashMap();
        for (final String parameterName : updateParams.keySet()) {
            if (null == parameterName) {
                continue;
            }
            String locateParamName = Strings.replace(parameterName, ".", "_");
            hql.append(parameterName).append(" = ").append(":").append(locateParamName).append(",");
            newParams.put(locateParamName, updateParams.get(locateParamName));
        }
        hql.deleteCharAt(hql.length() - 1);
        hql.append(" where ").append(attr).append(" in (:ids)");
        newParams.put("ids", values);
        return executeUpdate(hql.toString(), newParams);
    }

    public void remove(Collection<?> entities) {
        if (null == entities || entities.isEmpty())
            return;
        for (Object entity : entities)
            if (null != entity)
                getSession().delete(entity);
    }

    public void remove(Object... entities) {
        for (Object entity : entities) {
            if (null != entity) {
                if (entity instanceof Collection<?>) {
                    for (Object innerEntity : (Collection<?>) entity) {
                        getSession().delete(innerEntity);
                    }
                } else {
                    getSession().delete(entity);
                }
            }
        }
    }

    public boolean remove(Class<?> clazz, String attr, Object... values) {
        if (clazz == null || Strings.isEmpty(attr) || values == null || values.length == 0) {
            return false;
        }
        String entityName = modelMeta.getEntityType(clazz).getEntityName();
        StringBuilder hql = new StringBuilder();
        hql.append("delete from ").append(entityName).append(" where ").append(attr).append(" in (:ids)");
        Map<String, Object> parameterMap = CollectUtils.newHashMap();
        parameterMap.put("ids", values);
        return executeUpdate(hql.toString(), parameterMap) > 0;
    }

    public boolean remove(Class<?> entityClass, String attr, Collection<?> values) {
        return remove(entityClass, attr, values.toArray());
    }

    public boolean remove(Class<?> clazz, Map<String, Object> keyMap) {
        if (clazz == null || keyMap == null || keyMap.isEmpty()) {
            return false;
        }
        String entityName = modelMeta.getEntityType(clazz).getEntityName();
        StringBuilder hql = new StringBuilder();
        hql.append("delete from ").append(entityName).append(" where ");
        Set<String> keySet = keyMap.keySet();
        Map<String, Object> params = CollectUtils.newHashMap();
        for (final String keyName : keySet) {
            Object keyValue = keyMap.get(keyName);
            String paramName = keyName.replace('.', '_');
            params.put(paramName, keyValue);
            if (keyValue.getClass().isArray() || keyValue instanceof Collection<?>) {
                hql.append(keyName).append(" in (:").append(paramName).append(") and ");
            } else {
                hql.append(keyName).append(" = :").append(paramName).append(" and ");
            }
        }
        hql.append(" (1=1) ");
        return (executeUpdate(hql.toString(), params) > 0);
    }

    public long count(String entityName, String keyName, Object value) {
        String hql = "select count(*) from " + entityName + " where " + keyName + "=:value";
        Map<String, Object> params = CollectUtils.newHashMap();
        params.put("value", value);
        List<?> rs = search(hql, params);
        if (rs.isEmpty()) {
            return 0;
        } else {
            return ((Number) rs.get(0)).longValue();
        }
    }

    public long count(Class<?> entityClass, String keyName, Object value) {
        return count(entityClass.getName(), keyName, value);
    }

    public long count(Class<?> entityClass, String[] attrs, Object[] values, String countAttr) {
        Assert.isTrue(null != attrs && null != values && attrs.length == values.length);

        String entityName = entityClass.getName();
        StringBuilder hql = new StringBuilder();
        if (Strings.isNotEmpty(countAttr)) {
            hql.append("select count(distinct ").append(countAttr).append(") from ");
        } else {
            hql.append("select count(*) from ");
        }
        hql.append(entityName).append(" as entity where ");
        Map<String, Object> params = CollectUtils.newHashMap();
        for (int i = 0; i < attrs.length; i++) {
            if (Strings.isEmpty(attrs[i])) {
                continue;
            }
            String keyName = Strings.replace(attrs[i], ".", "_");
            Object keyValue = values[i];
            params.put(keyName, keyValue);
            if (keyValue != null && (keyValue.getClass().isArray() || keyValue instanceof Collection<?>)) {
                hql.append("entity.").append(attrs[i]).append(" in (:").append(keyName).append(')');
            } else {
                hql.append("entity.").append(attrs[i]).append(" = :").append(keyName);
            }
            if (i < attrs.length - 1)
                hql.append(" and ");
        }
        return ((Number) search(hql.toString(), params).get(0)).longValue();
    }

    public boolean exist(Class<?> entityClass, String attr, Object value) {
        return count(entityClass, attr, value) > 0;
    }

    public boolean exist(String entityName, String attr, Object value) {
        return count(entityName, attr, value) > 0;
    }

    public boolean exist(Class<?> entity, String[] attrs, Object[] values) {
        return (count(entity, attrs, values, null) > 0);
    }

    /**
     * ??
     * 
     * @param clazz
     * @param id
     * @param codeName
     * @param codeValue
     * @return boolean(?) entityId?entity
     */
    public boolean duplicate(Class<? extends Entity<?>> clazz, Serializable id, String codeName, Object codeValue) {
        if (null != codeValue && Strings.isNotEmpty(codeValue.toString())) {
            List<? extends Entity<?>> list = get(clazz, codeName, new Object[] { codeValue });
            if (list != null && !list.isEmpty()) {
                if (id == null) {
                    return true;
                } else {
                    for (Iterator<? extends Entity<?>> it = list.iterator(); it.hasNext();) {
                        Entity<?> info = it.next();
                        if (!info.getId().equals(id))
                            return true;
                    }
                    return false;
                }
            }
        }
        return false;
    }

    public boolean duplicate(String entityName, Serializable id, Map<String, Object> params) {
        StringBuilder b = new StringBuilder("from ");
        b.append(entityName).append(" where (1=1)");
        Map<String, Object> paramsMap = CollectUtils.newHashMap();
        int i = 0;
        for (Iterator<String> iterator = params.keySet().iterator(); iterator.hasNext(); i++) {
            String key = iterator.next();
            b.append(" and ").append(key).append('=').append(":param" + i);
            paramsMap.put("param" + i, params.get(key));
        }
        List<?> list = search(b.toString(), paramsMap);
        if (!list.isEmpty()) {
            if (null == id) {
                return false;
            } else {
                for (Iterator<?> iter = list.iterator(); iter.hasNext();) {
                    Entity<?> one = (Entity<?>) iter.next();
                    if (!one.getId().equals(id))
                        return false;
                }
            }
        }
        return true;
    }

    /**
     * 
     * 
     * @param query
     * @return query string
     */
    private String buildCountQueryStr(Query query) {
        String queryStr = "select count(*) ";
        if (query instanceof SQLQuery) {
            queryStr += "from (" + query.getQueryString() + ")";
        } else {
            String lowerCaseQueryStr = query.getQueryString().toLowerCase();
            String selectWhich = lowerCaseQueryStr.substring(0, query.getQueryString().indexOf("from"));
            int indexOfDistinct = selectWhich.indexOf("distinct");
            int indexOfFrom = lowerCaseQueryStr.indexOf("from");
            // ?distinct
            if (-1 != indexOfDistinct) {
                if (Strings.contains(selectWhich, ",")) {
                    queryStr = "select count("
                            + query.getQueryString().substring(indexOfDistinct, query.getQueryString().indexOf(","))
                            + ")";
                } else {
                    queryStr = "select count(" + query.getQueryString().substring(indexOfDistinct, indexOfFrom)
                            + ")";
                }
            }
            queryStr += query.getQueryString().substring(indexOfFrom);
        }
        return queryStr;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public static final class QuerySupport {
        private QuerySupport() {
            super();
        }

        private static Query buildHibernateQuery(org.beangle.commons.dao.query.Query<?> bquery,
                final Session session) {
            Query hibernateQuery = null;
            if (bquery.getLang().equals(org.beangle.commons.dao.query.Lang.HQL)) {
                hibernateQuery = session.createQuery(bquery.getStatement());
            } else {
                hibernateQuery = session.createSQLQuery(bquery.getStatement());
            }
            if (bquery.isCacheable())
                hibernateQuery.setCacheable(bquery.isCacheable());
            setParameter(hibernateQuery, bquery.getParams());
            return hibernateQuery;
        }

        /**
         * 
         * 
         * @param limitQuery
         * @param hibernateSession
         * @return data count
         */
        public static int count(final org.beangle.commons.dao.query.LimitQuery<?> limitQuery,
                final Session hibernateSession) {
            final org.beangle.commons.dao.query.Query<?> cntQuery = limitQuery.getCountQuery();
            if (null == cntQuery) {
                Query hibernateQuery = buildHibernateQuery(limitQuery, hibernateSession);
                return hibernateQuery.list().size();
            } else {
                Query hibernateQuery = buildHibernateQuery(cntQuery, hibernateSession);
                final Number count = (Number) (hibernateQuery.uniqueResult());
                if (null == count) {
                    return 0;
                } else {
                    return count.intValue();
                }
            }
        }

        /**
         * 
         * 
         * @param query
         * @param session
         * @return result list
         */
        @SuppressWarnings("unchecked")
        public static <T> List<T> find(final org.beangle.commons.dao.query.Query<T> query, final Session session) {
            if (query instanceof LimitQuery<?>) {
                LimitQuery<T> limitQuery = (LimitQuery<T>) query;
                Query hibernateQuery = buildHibernateQuery(limitQuery, session);
                if (null == limitQuery.getLimit()) {
                    return hibernateQuery.list();
                } else {
                    final PageLimit limit = limitQuery.getLimit();
                    hibernateQuery.setFirstResult((limit.getPageNo() - 1) * limit.getPageSize())
                            .setMaxResults(limit.getPageSize());
                    return hibernateQuery.list();
                }
            } else {
                return buildHibernateQuery(query, session).list();
            }
        }

        /**
         * queryJPA style?
         * 
         * @param query
         * @param argument
         */
        public static Query setParameter(final Query query, final Object[] argument) {
            if (argument != null && argument.length > 0) {
                for (int i = 0; i < argument.length; i++)
                    query.setParameter(String.valueOf(i + 1), argument[i]);
            }
            return query;
        }

        /**
         * query?
         * 
         * @param query
         * @param parameterMap
         * @return query
         */
        public static Query setParameter(final Query query, final Map<String, Object> parameterMap) {
            if (parameterMap != null && !parameterMap.isEmpty()) {
                for (final Iterator<String> ite = parameterMap.keySet().iterator(); ite.hasNext();) {
                    final String parameterName = ite.next();
                    if (null == parameterName) {
                        break;
                    }
                    final Object parameterValue = parameterMap.get(parameterName);
                    if (null == parameterValue) {
                        query.setParameter(parameterName, (Object) null);
                    } else if (parameterValue.getClass().isArray()) {
                        query.setParameterList(parameterName, (Object[]) parameterValue);
                    } else if (parameterValue instanceof Collection<?>) {
                        query.setParameterList(parameterName, (Collection<?>) parameterValue);
                    } else {
                        query.setParameter(parameterName, parameterValue);
                    }
                }
            }
            return query;
        }

        /**
         * ?
         * 
         * @param query
         * @param conditions
         */
        public static void bindValues(final Query query, final List<Condition> conditions) {
            int position = 0;
            boolean hasInterrogation = false; // ??
            for (final Iterator<Condition> iter = conditions.iterator(); iter.hasNext();) {
                final Condition condition = (Condition) iter.next();
                if (Strings.contains(condition.getContent(), "?")) {
                    hasInterrogation = true;
                }
                if (hasInterrogation) {
                    for (final Iterator<?> iterator = condition.getParams().iterator(); iterator.hasNext();) {
                        query.setParameter(position++, iterator.next());
                    }
                } else {
                    final List<String> paramNames = condition.getParamNames();
                    for (int i = 0; i < paramNames.size(); i++) {
                        final String name = paramNames.get(i);
                        final Object value = condition.getParams().get(i);
                        if (value.getClass().isArray()) {
                            query.setParameterList(name, (Object[]) value);
                        } else if (value instanceof Collection<?>) {
                            query.setParameterList(name, (Collection<?>) value);
                        } else {
                            query.setParameter(name, value);
                        }
                    }
                }
            }
        }
    }

    public void setModelMeta(ModelMeta modelMeta) {
        this.modelMeta = modelMeta;
    }

}