com.itrus.ca.common.persistence.BaseDaoImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.itrus.ca.common.persistence.BaseDaoImpl.java

Source

/**
 * Copyright &copy; 2012-2013 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.itrus.ca.common.persistence;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.QueryWrapperFilter;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.util.Version;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.filter.impl.CachingWrapperFilter;
import org.hibernate.search.query.DatabaseRetrievalMethod;
import org.hibernate.search.query.ObjectLookupMethod;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.wltea.analyzer.lucene.IKAnalyzer;

import com.alibaba.druid.pool.DruidDataSource;
import com.itrus.ca.common.annotation.VOAnnotation;
import com.itrus.ca.common.utils.ReflectHelper;
import com.itrus.ca.common.utils.Reflections;
import com.itrus.ca.common.utils.StringHelper;
import com.itrus.ca.common.utils.StringUtils;

/**
 * DAO?
 * 
 * @author ThinkGem
 * @version 2013-05-15
 * @param <T>
 */
public class BaseDaoImpl<T> implements BaseDao<T> {

    /**
     * ??
     */
    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private DataSource dataSource;

    /**
     * ()
     */
    private Class<?> entityClass;

    /**
     * ??
     */
    public BaseDaoImpl() {
        entityClass = Reflections.getClassGenricType(getClass());
    }

    /**
     * ??
     */
    public EntityManager getEntityManager() {
        return entityManager;
    }

    /**
     * ? Session
     */
    public Session getSession() {
        return (Session) getEntityManager().getDelegate();
    }

    /**
     * ??
     */
    public void flush() {
        getSession().flush();
    }

    /**
     * ?
     */
    public void clear() {
        getSession().clear();
    }

    // -------------- QL Query --------------

    /**
     * QL 
     * 
     * @param page
     * @param qlString
     * @param parameter
     * @return
     */
    @SuppressWarnings("unchecked")
    public <E> Page<E> find(Page<E> page, String qlString, Object... parameter) {
        // get count
        if (!page.isDisabled() && !page.isNotCount()) {
            String countQlString = "select count(*) " + removeSelect(removeOrders(qlString));
            // page.setCount(Long.valueOf(createQuery(countQlString,
            // parameter).uniqueResult().toString()));
            Query query = createQuery(countQlString, parameter);
            List<Object> list = query.list();
            if (list.size() > 0) {
                page.setCount(Long.valueOf(list.get(0).toString()));
            } else {
                page.setCount(list.size());
            }
            if (page.getCount() < 1) {
                return page;
            }
        }
        // order by
        String ql = qlString;
        if (StringUtils.isNotBlank(page.getOrderBy())) {
            ql += " order by " + page.getOrderBy();
        }
        Query query = createQuery(ql, parameter);
        // set page
        if (!page.isDisabled()) {
            query.setFirstResult(page.getFirstResult());
            query.setMaxResults(page.getMaxResults());
        }
        page.setList(query.list());
        return page;
    }

    /**
     * QL 
     * 
     * @param qlString
     * @param parameter
     * @return
     */
    @SuppressWarnings("unchecked")
    public <E> List<E> find(String qlString, Object... parameter) {
        Query query = createQuery(qlString, parameter);
        return query.list();
    }

    /**
     * QL 
     * 
     * @param qlString
     * @param parameter
     * @return
     */
    @Transactional(readOnly = false)
    public int update(String qlString, Object... parameter) {
        return createQuery(qlString, parameter).executeUpdate();
    }

    /**
     *  QL 
     * 
     * @param qlString
     * @param parameter
     * @return
     */
    public Query createQuery(String qlString, Object... parameter) {
        Query query = getSession().createQuery(qlString);
        setParameter(query, parameter);
        return query;
    }

    // -------------- SQL Query --------------

    /**
     * SQL 
     * 
     * @param page
     * @param sqlString
     * @param parameter
     * @return
     */
    public <E> Page<E> findBySql(Page<E> page, String sqlString, Object... parameter) {
        return findBySql(page, sqlString, null, parameter);
    }

    public void exeSql(String sql) {
        Logger log = Logger.getLogger("ex");
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = dataSource.getConnection();
            conn.setAutoCommit(false);
            ps = conn.prepareStatement(sql);
            ps.execute();
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(StringHelper.getStackInfo(e));
        } finally {
            try {
                if (ps != null)
                    ps.close();
                if (conn != null)
                    conn.close();
            } catch (SQLException e1) {
                e1.printStackTrace();
                log.error(StringHelper.getStackInfo(e1));
            }
        }
    }

    // @Transactional(readOnly = false)
    // public void exeSql(final String sql) {
    // try {
    // getSession().doReturningWork(new ReturningWork() {
    // public SQLQuery execute(Connection connection)
    // throws SQLException {
    //
    // Session session = getSession();
    // try {
    // org.hibernate.Transaction tx = session.getTransaction();
    // tx.begin();
    // // session.getTransaction();
    // session.createSQLQuery(sql).executeUpdate();
    // tx.commit();
    // } catch (Exception e) {
    // e.printStackTrace();
    // Logger log = Logger.getLogger("ex");
    // log.error(StringHelper.getStackInfo(e));
    // }
    // return null;
    // }
    // });
    // } catch (Exception e) {
    // // e.printStackTrace();
    // Logger log = Logger.getLogger("ex");
    // log.error(StringHelper.getStackInfo(e));
    // }
    // }

    /**
     * SQL 
     * 
     * @param page
     * @param sqlString
     * @param resultClass
     * @param parameter
     * @return
     */
    @SuppressWarnings("unchecked")
    public <E> Page<E> findBySql(Page<E> page, String sqlString, Class<?> resultClass, Object... parameter) {
        // get count
        if (!page.isDisabled() && !page.isNotCount()) {
            String countSqlString = "select count(*) " + removeSelect(removeOrders(sqlString));
            // page.setCount(Long.valueOf(createSqlQuery(countSqlString,
            // parameter).uniqueResult().toString()));
            Query query = createSqlQuery(countSqlString, parameter);
            List<Object> list = query.list();
            if (list.size() > 0) {
                page.setCount(Long.valueOf(list.get(0).toString()));
            } else {
                page.setCount(list.size());
            }
            if (page.getCount() < 1) {
                return page;
            }
        }
        // order by
        String sql = sqlString;
        if (StringUtils.isNotBlank(page.getOrderBy())) {
            sql += " order by " + page.getOrderBy();
        }
        SQLQuery query = createSqlQuery(sql, parameter);
        // set page
        if (!page.isDisabled()) {
            query.setFirstResult(page.getFirstResult());
            query.setMaxResults(page.getMaxResults());
        }
        setResultTransformer(query, resultClass);
        page.setList(query.list());
        return page;
    }

    /**
     * SQL 
     * 
     * @param sqlString
     * @param parameter
     * @return
     */
    public <E> List<E> findBySql(String sqlString, Object... parameter) {
        return findBySql(sqlString, null, parameter);
    }

    /**
     * SQL 
     * 
     * @param sqlString
     * @param resultClass
     * @param parameter
     * @return
     */
    @SuppressWarnings("unchecked")
    public <E> List<E> findBySql(String sqlString, Class<?> resultClass, Object... parameter) {
        SQLQuery query = createSqlQuery(sqlString, parameter);
        setResultTransformer(query, resultClass);
        return query.list();
    }

    /**
     * SQL 
     * 
     * @param sqlString
     * @param parameter
     * @return
     */
    @Transactional(readOnly = false)
    public int updateBySql(String sqlString, Object... parameter) {
        return createSqlQuery(sqlString, parameter).executeUpdate();
    }

    /**
     *  SQL 
     * 
     * @param sqlString
     * @param parameter
     * @return
     */
    public SQLQuery createSqlQuery(String sqlString, Object... parameter) {
        SQLQuery query = getSession().createSQLQuery(sqlString);
        setParameter(query, parameter);
        return query;
    }

    // -------------- Query Tools --------------

    /**
     * 
     * 
     * @param query
     * @param resultClass
     */
    private void setResultTransformer(SQLQuery query, Class<?> resultClass) {
        if (resultClass != null) {
            if (resultClass == Map.class) {
                query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
            } else if (resultClass == List.class) {
                query.setResultTransformer(Transformers.TO_LIST);
            } else {
                query.setResultTransformer(Transformers.aliasToBean(resultClass));
                // query.addEntity(resultClass);
            }
        }
    }

    /**
     * ?
     * 
     * @param query
     * @param parameter
     */
    private void setParameter(Query query, Object... parameter) {
        if (parameter != null) {
            for (int i = 0; i < parameter.length; i++) {
                query.setParameter(i, parameter[i]);
            }
        }
    }

    /**
     * qlStringselect??
     * 
     * @param hql
     * @return
     */
    private String removeSelect(String qlString) {
        int beginPos = qlString.toLowerCase().indexOf("from");
        return qlString.substring(beginPos);
    }

    /**
     * hqlorderBy??
     * 
     * @param hql
     * @return
     */
    private String removeOrders(String qlString) {
        Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(qlString);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }

    // -------------- Criteria --------------

    /**
     * 
     * 
     * @param page
     * @return
     */
    public Page<T> find(Page<T> page) {
        return find(page, createDetachedCriteria());
    }

    /**
     * 
     * 
     * @param page
     * @param detachedCriteria
     * @param resultTransformer
     * @return
     */
    public Page<T> find(Page<T> page, DetachedCriteria detachedCriteria) {
        return find(page, detachedCriteria, Criteria.DISTINCT_ROOT_ENTITY);
    }

    @SuppressWarnings("unchecked")
    public List<T> manyFind(DetachedCriteria detachedCriteria, ResultTransformer resultTransformer, int size) {
        Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
        criteria.setResultTransformer(resultTransformer);
        criteria.setFirstResult(0);
        criteria.setMaxResults(size);
        return criteria.list();
    }

    /**
     * 
     * 
     * @param page
     * @param detachedCriteria
     * @param resultTransformer
     * @return
     */
    @SuppressWarnings("unchecked")
    public Page<T> find(Page<T> page, DetachedCriteria detachedCriteria, ResultTransformer resultTransformer) {
        // get count
        if (!page.isDisabled() && !page.isNotCount()) {
            page.setCount(count(detachedCriteria));
            if (page.getCount() < 1) {
                return page;
            }
        }
        Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
        criteria.setResultTransformer(resultTransformer);
        // set page
        if (!page.isDisabled()) {
            criteria.setFirstResult(page.getFirstResult());
            criteria.setMaxResults(page.getMaxResults());
        }
        // order by
        if (StringUtils.isNotBlank(page.getOrderBy())) {
            for (String order : StringUtils.split(page.getOrderBy(), ",")) {
                String[] o = StringUtils.split(order, " ");
                if (o.length == 1) {
                    criteria.addOrder(Order.asc(o[0]));
                } else if (o.length == 2) {
                    if ("DESC".equals(o[1].toUpperCase())) {
                        criteria.addOrder(Order.desc(o[0]));
                    } else {
                        criteria.addOrder(Order.asc(o[0]));
                    }
                }
            }
        }
        page.setList(criteria.list());
        return page;
    }

    /**
     * 
     * 
     * @param detachedCriteria
     * @return
     */
    public List<T> find(DetachedCriteria detachedCriteria) {
        return find(detachedCriteria, Criteria.DISTINCT_ROOT_ENTITY);
    }

    /**
     * 
     * 
     * @param detachedCriteria
     * @param resultTransformer
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> find(DetachedCriteria detachedCriteria, ResultTransformer resultTransformer) {
        Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
        criteria.setResultTransformer(resultTransformer);
        return criteria.list();
    }

    /**
     * 
     * 
     * @param detachedCriteria
     * @return
     */
    @SuppressWarnings("rawtypes")
    public long count(DetachedCriteria detachedCriteria) {
        Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
        long totalCount = 0;
        try {
            // Get orders
            Field field = CriteriaImpl.class.getDeclaredField("orderEntries");
            field.setAccessible(true);
            List orderEntrys = (List) field.get(criteria);
            // Remove orders
            field.set(criteria, new ArrayList());
            // Get count
            criteria.setProjection(Projections.rowCount());
            totalCount = Long.valueOf(criteria.uniqueResult().toString());
            // Clean count
            criteria.setProjection(null);
            // Restore orders
            field.set(criteria, orderEntrys);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return totalCount;
    }

    /**
     * ?
     * 
     * @param criterions
     *            Restrictions.eq("name", value);
     * @return
     */
    public DetachedCriteria createDetachedCriteria(Criterion... criterions) {
        DetachedCriteria dc = DetachedCriteria.forClass(entityClass);
        for (Criterion c : criterions) {
            dc.add(c);
        }
        return dc;
    }

    // -------------- Hibernate search --------------

    /**
     * ?Session
     */
    public FullTextSession getFullTextSession() {
        return Search.getFullTextSession(getSession());
    }

    /**
     * 
     */
    public void createIndex() {
        try {
            getFullTextSession().createIndexer(entityClass).startAndWait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 
     * 
     * @param page
     *            
     * @param query
     *            
     * @param queryFilter
     *            
     * @param sort
     *            ?
     * @return 
     */
    @SuppressWarnings("unchecked")
    public Page<T> search(Page<T> page, BooleanQuery query, BooleanQuery queryFilter, Sort sort) {

        // 
        FullTextQuery fullTextQuery = getFullTextSession().createFullTextQuery(query, entityClass);

        // 
        if (queryFilter != null) {
            fullTextQuery.setFilter(new CachingWrapperFilter(new QueryWrapperFilter(queryFilter)));
        }

        // ?
        if (sort != null) {
            fullTextQuery.setSort(sort);
        }

        // 
        page.setCount(fullTextQuery.getResultSize());
        fullTextQuery.setFirstResult(page.getFirstResult());
        fullTextQuery.setMaxResults(page.getMaxResults());

        // ??
        fullTextQuery.initializeObjectsWith(ObjectLookupMethod.SECOND_LEVEL_CACHE, DatabaseRetrievalMethod.QUERY);

        // 
        page.setList(fullTextQuery.list());

        return page;
    }

    /**
     * ?
     */
    public BooleanQuery getFullTextQuery(BooleanClause... booleanClauses) {
        BooleanQuery booleanQuery = new BooleanQuery();
        for (BooleanClause booleanClause : booleanClauses) {
            booleanQuery.add(booleanClause);
        }
        return booleanQuery;
    }

    /**
     * ?
     * 
     * @param q
     *            
     * @param fields
     *            
     * @return 
     */
    public BooleanQuery getFullTextQuery(String q, String... fields) {
        Analyzer analyzer = new IKAnalyzer();
        BooleanQuery query = new BooleanQuery();
        try {
            if (StringUtils.isNotBlank(q)) {
                for (String field : fields) {
                    QueryParser parser = new QueryParser(Version.LUCENE_36, field, analyzer);
                    query.add(parser.parse(q), Occur.SHOULD);
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return query;
    }

    /**
     * 
     * 
     * @param query
     *            
     * @param list
     *            
     * @param subLength
     *            ?
     * @param fields
     *            ??
     */
    public List<T> keywordsHighlight(BooleanQuery query, List<T> list, int subLength, String... fields) {
        Analyzer analyzer = new IKAnalyzer();
        Formatter formatter = new SimpleHTMLFormatter("<span class=\"highlight\">", "</span>");
        Highlighter highlighter = new Highlighter(formatter, new QueryScorer(query));
        highlighter.setTextFragmenter(new SimpleFragmenter(subLength));
        for (T entity : list) {
            try {
                for (String field : fields) {
                    String text = StringUtils.replaceHtml((String) Reflections.invokeGetter(entity, field));
                    String description = highlighter.getBestFragment(analyzer, field, text);
                    if (description != null) {
                        Reflections.invokeSetter(entity, fields[0], description);
                        break;
                    }
                    Reflections.invokeSetter(entity, fields[0], StringUtils.abbr(text, subLength * 2));
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InvalidTokenOffsetsException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    // ------------------- add

    /**
     * 
     * ???<br>
     * hibernateBUG<br>
     * ???,SQLsqlDB?<br>
     * SQL?...<br>
     * 
     * @param page
     * @param sqlString
     * @param resultClass
     * @param returnVO
     *            - VO?,<br>
     *            - ?resultClass<br>
     * @return
     */
    public <E> Page<E> findBySqlString(Page<E> page, String sqlString, Class[] resultClass, Class returnVO) {
        return findBySqlString(page, sqlString, null, resultClass, returnVO);
    }

    /**
     * ???<br>
     * hibernateBUG<br>
     * ???,SQLsqlDB?<br>
     * SQL?...<br>
     * 
     * @param page
     * @param sqlString
     * @param parameter
     * @param resultClass
     * @param returnVO
     *            - VO?,<br>
     *            - ?resultClass<br>
     * @return
     */
    public <E> Page<E> findBySqlStringParameter(Page<E> page, String sqlString, Parameter parameter,
            Class[] resultClass, Class returnVO) {
        return findBySqlString(page, sqlString, parameter, resultClass, returnVO);
    }

    /**
     * SQL 
     * 
     * @param page
     * @param sqlString
     * @param resultClass
     * @param parameter
     * @return
     */
    public <E> Page<E> findBySql(Page<E> page, String sqlString, Parameter parameter, Class<?> resultClass) {
        return findBySqlString(page, sqlString, parameter, new Class[] { resultClass }, null);
    }

    public <E> Page<E> findBySqlString(Page<E> page, String sqlString, Class[] resultClass) {
        return findBySqlString(page, sqlString, null, resultClass, null);
    }

    private void setResultTransformer(SQLQuery query, Class[] resultClass) {
        if (resultClass == null || resultClass.length <= 0)
            return;
        for (Class cls : resultClass) {
            query.addEntity(cls);

        }
    }

    @SuppressWarnings("unchecked")
    public <E> Page<E> findBySqlString(Page<E> page, String sqlString, Parameter parameter, Class[] resultClass,
            Class returnVO) {
        // get count
        if (!page.isDisabled() && !page.isNotCount()) {
            String select = StringHelper.isNull(page.getCountDistinctColumn()) ? "select count(*) "
                    : "select count(distinct " + page.getCountDistinctColumn() + ") ";
            String countSqlString = select + removeSelect(removeOrders(sqlString));
            // page.setCount(Long.valueOf(createSqlQuery(countSqlString,
            // parameter).uniqueResult().toString()));
            Query query = createSqlQuery(countSqlString, parameter);
            List<Object> list = query.list();
            if (list.size() > 0) {
                page.setCount(Long.valueOf(list.get(0).toString()));
            } else {
                page.setCount(list.size());
            }
            if (page.getCount() < 1) {
                return page;
            }
        }
        String sql = sqlString;
        // group by
        if (StringUtils.isNotBlank(page.getGroupBy())) {
            sql += " group by " + page.getGroupBy();
        }
        // order by
        if (StringUtils.isNotBlank(page.getOrderBy())) {
            sql += " order by " + page.getOrderBy();
        }
        SQLQuery query = createSqlQuery(sql, parameter);
        // set page
        if (!page.isDisabled()) {
            query.setFirstResult(page.getFirstResult());
            query.setMaxResults(page.getMaxResults());
        }

        boolean isMutilReturn = false;
        if (resultClass != null && resultClass.length == 1)
            setResultTransformer(query, resultClass[0]);
        else if (resultClass != null && resultClass.length > 1) {
            setResultTransformer(query, resultClass);
            isMutilReturn = true;
        }
        List l = query.list();

        page.setList(query.list());

        if (isMutilReturn)
            setResultReturnVO(returnVO, page);

        return page;
    }

    @SuppressWarnings("unchecked")
    public <E> Page<E> find(Page<E> page, String qlString, Parameter parameter, Class[] resultClass,
            Class returnVO) {
        // get count
        if (!page.isDisabled() && !page.isNotCount()) {
            String countQlString = "select count(*) " + removeSelect(removeOrders(qlString));
            // page.setCount(Long.valueOf(createQuery(countQlString,
            // parameter).uniqueResult().toString()));
            Query query = createQuery(countQlString, parameter);
            List<Object> list = query.list();
            if (list.size() > 0) {
                page.setCount(Long.valueOf(list.get(0).toString()));
            } else {
                page.setCount(list.size());
            }
            if (page.getCount() < 1) {
                return page;
            }
        }
        String ql = qlString;
        // group by
        if (StringUtils.isNotBlank(page.getGroupBy())) {
            ql += " group by " + page.getGroupBy();
        }
        // order by

        if (StringUtils.isNotBlank(page.getOrderBy())) {
            ql += " order by " + page.getOrderBy();
        }
        Query query = createQuery(ql, parameter);
        // set page
        if (!page.isDisabled()) {
            query.setFirstResult(page.getFirstResult());
            query.setMaxResults(page.getMaxResults());
        }
        page.setList(query.list());

        boolean isMutilReturn = false;

        if (resultClass != null && resultClass.length > 1)
            isMutilReturn = true;

        if (isMutilReturn)
            setResultReturnVO(returnVO, page);
        return page;
    }

    private void setResultReturnVO(Class returnVO, Page result) {
        List<Class> lst = null;
        List<Object[]> o = result.getList();
        List resList = new ArrayList();
        if (returnVO == null)
            return;
        try {
            // ????
            lst = ReflectHelper.getAllvarClass(returnVO);

            // 
            for (Object[] e : o) {
                Object obj = returnVO.newInstance();
                // e=Object[]{a,b}
                // 
                for (Object ef : e) {
                    // ??
                    for (Class cls : lst) {
                        // ?set
                        if (cls.equals(ef.getClass())) {
                            try {
                                VOAnnotation vo = ReflectHelper.getAnnotationByClass(returnVO, cls,
                                        VOAnnotation.class);
                                ReflectHelper.setValue(obj, vo.varName(), ef);
                            } catch (IllegalArgumentException | InvocationTargetException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            }
                        }
                    }
                }
                resList.add(obj);
            }
            result.setList(resList);
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    public List<T> manyFind(DetachedCriteria detachedCriteria, int size) {
        return manyFind(detachedCriteria, Criteria.DISTINCT_ROOT_ENTITY, size);
    }

    public List<Map> findBySQLListMap(final String sql, final int pageNo, final int numPerPage)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
            ClassNotFoundException, InstantiationException {

        List<Map> l = findBySQL(sql, pageNo, numPerPage).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .list();
        return l;

    }

    public SQLQuery findBySQL(final String sql, final int pageNo, final int numPerPage) {
        return (SQLQuery) (T) getSession().doReturningWork(new ReturningWork() {
            public SQLQuery execute(Connection connection) throws SQLException {
                SQLQuery sqlQuery = getSession().createSQLQuery(sql);
                if (pageNo > 0) {
                    sqlQuery.setFirstResult((pageNo - 1) * numPerPage);
                    sqlQuery.setMaxResults(numPerPage);
                }

                return sqlQuery;
            }
        });
    }

}