Hibernate泛型DAO接口,大部分通用都已包括

过了大半年,来把这个更新下。
Hibernate通用泛型DAO,执行一些通用操作。简单封装一些操作。相互印证学习。Hibernate整合Spring的配置等在此略过。

首说下DAO接口,由于有的方法是后来补充的,所以注释不全,详细的说明可以在实现类里看到。
如果你要运行测试实例,将3个类拷贝到自己的项目中,按测试示例写测试用例。

DAO接口:
package com.blog.dao;

import org.hibernate.ScrollableResults;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 功能:超级DAO接口,通过使用泛型,将所有的dao操作定义;
 * iterator方法操作大量数据时会溢出,注意使用情景,使用srcoll可以获取比较好的性能
 * 如果dml操作涉及大量数据且会填充2级缓存时,在此方法中执行sql语句前必须关闭2级缓存,语句执行后清除缓存
 * Author: DR.YangLong
 * Date: 14-1-15
 * Time: 下午3:56
 * Email:[email protected]
 */
public interface SupperBaseDAO<T> {
    /**
     * 保存
     *
     * @param object 需保存对象
     * @return 影响行数
     */
    public Serializable save(final T object);

    /**
     * 更新对象持久化信息,必须带有主键
     *
     * @param object 需更新对象
     */
    public void update(final T object);

    /**
     * 删除对象持久化信息,必须带有主键
     *
     * @param object 需删除对象
     */
    public void delete(final T object);

    /**
     * 使用SQL语句删除记录
     *
     * @param id id
     */
    public void delete(final Serializable id);

    /**
     * 根据Id查找对象
     *
     * @param id id
     * @return T
     */
    public <T> T findById(final Serializable id);

    /**
     * 根据Id查找对象
     *
     * @param id id
     * @return T
     */
    public <T> T loadById(final Serializable id);

    /**
     * 根据唯一属性get对象
     *
     * @param propertyName 属性名称
     * @param value        属性值
     * @return T
     */
    public <T> T findByProperty(final String propertyName, final Object value);

    /**
     * 根据唯一属性值对获取对象
     *
     * @param propertyNames 属性名称数组
     * @param values        属性值数组
     * @param <T>           泛型
     * @return T
     */
    public <T> T findByProperties(final String[] propertyNames, final Object[] values);

    /**
     * 查询实体
     *
     * @param object
     * @param <T>
     * @return
     */
    public <T> T findByEntity(final T object) throws IllegalAccessException;

    /**
     * 同步并清空数据库连接session缓存
     */
    public void flushANDclear();

    /**
     * 强制清空缓存
     */
    public void clean();

    /**
     * 强制同步到数据库
     */
    public void flush();

    /**
     * 查找所有对象
     * 数据量很大时,此方法会溢出
     *
     * @return List<T>
     */
    public <T> List<T> findAll();

    /**
     * 分页查询所有记录,HQL
     *
     * @param propertyName 排序属性名称
     * @param desc         是否倒序
     * @param startRow     起始记录
     * @param pageSize     分页大小
     * @param <T>
     * @return
     */
    public <T> List<T> findAllByPage(final String propertyName, final boolean desc, final Integer startRow, final Integer pageSize);

    /**
     * 查询类对应的所有记录行数
     *
     * @return Long
     */
    public Long findAllCount();

    /**
     * 查询所有对象,对于数据量很大时,此方法会溢出
     *
     * @param <T> 泛型
     * @return 所有记录
     */
    public <T> List<T> findAllIterator();

    /**
     * 使用hibernate的iterator方法分页查询,对于2级缓存中已存在大量需查询对象,或预期查询结果包含大量相同对象
     * 或存在很多不使用对象时此方法可提升性能
     *
     * @param HQL      HQL查询语句
     * @param startRow 开始行数
     * @param pageSize 页码
     * @param <T>      泛型
     * @return List
     */
    public <T> List<T> batchGetDataIteratorByHQL(final String HQL, final Integer startRow, final Integer pageSize);

    /**
     * 游标查询,大量数据时会获得较高性能
     * 使用HQL语句进行查询,使用游标,
     *
     * @param HQL      HQL查询语句
     * @param startRow 起始行
     * @param pageSize 要查询多少行
     * @return ScrollableResults
     */
    public ScrollableResults batchGetDataScrollByHQL(final String HQL, final Integer startRow, final Integer pageSize);

    /**
     * 游标查询,大量数据时会获得较高性能
     * 使用SQL语句进行查询,使用游标,
     *
     * @param SQL      SQL查询语句
     * @param startRow 起始行
     * @param pageSize 要查询多少行
     * @return ScrollableResults
     */
    public ScrollableResults batchGetDataScrollBySQL(final String SQL, final Integer startRow, final Integer pageSize);

    /**
     * HQL查询总数
     *
     * @param HQL HQL语句
     * @return 记录数
     */
    public Long findCountByHQL(final String HQL);

    /**
     * 用HQL语句获取对象列表
     *
     * @param HQL      HQL语句
     * @param startRow 起始行数
     * @param pageSize 分页大小
     * @param <T>
     * @return
     */
    public <T> List<T> findObjsByHQL(final String HQL, final Integer startRow, final Integer pageSize);

    /**
     * SQL查询总数
     *
     * @param SQL
     * @return
     */
    public Long findCountBySQL(final String SQL);

    /**
     * 根据属性分页查询对象链表,数组实现,HQL
     *
     * @param propertyNames
     * @param values
     * @param startRow
     * @param pageSize
     * @param sortColumn
     * @param isDesc
     * @return
     */
    public <T> List<T> findByProperty(final String[] propertyNames, final Object[] values, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isDesc);

    /**
     * 获取记录总数
     *
     * @param propertyNames
     * @param values
     * @return
     */
    public Long findByPropertyCount(final String[] propertyNames, final Object[] values);

    /**
     * 根据一个属性值分页查询对象链表,HQL
     *
     * @param propertyName
     * @param value
     * @param startRow
     * @param pageSize
     * @param sortColumn
     * @param isDesc
     * @return
     */
    public <T> List<T> findByProperty(final String propertyName, final Object value, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isDesc);

    /**
     * 获取记录总数
     *
     * @param propertyName
     * @param value
     * @return
     */
    public Long findByPropertyCount(final String propertyName, final Object value);

    /**
     * 根据对象分页查询对象链表,HQL
     *
     * @param object
     * @param startRow
     * @param pageSize
     * @param sortColumn
     * @param isDesc
     * @return
     */
    public <T> List<T> findByProperty(final T object, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isDesc);

    /**
     * 查询记录总数
     *
     * @param object
     * @return
     */
    public Long findByPropertyCount(final T object);

    /**
     * 根据属性值分页查询对象链表,map实现,HQL
     *
     * @param map
     * @param startRow
     * @param pageSize
     * @param sortColumn
     * @param isDesc
     * @return
     */
    public <T> List<T> findByProperty(final Map<String, Object> map, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isDesc);

    /**
     * 查询记录总数
     *
     * @param map
     * @return
     */
    public Long findByPropertyCount(final Map<String, Object> map);

    /**
     * 通过sql语句查询对象链表
     *
     * @param sql
     * @param values
     * @return
     */
    public <T> List<T> findBySql(final String sql, final Object... values);

    /**
     * 查询记录总数
     *
     * @param sql
     * @param values
     * @return
     */
    public Long findBySqlCount(final String sql, final Object... values);

    /**
     * 通过SQL语句查询唯一对象
     *
     * @param sql
     * @param values
     * @return
     */
    public <T> T findUniqueBySql(final String sql, final Object... values);

    /**
     * 通过SQL语句批量更新或删除
     *
     * @param sql
     * @param values
     * @return
     */
    public int batchUpdateOrDelete(final String sql, final Object... values);

    /**
     * 通过HQL语句执行批量插入
     *
     * @param objects
     * @param size
     */
    public void batchInsertByHQL(final List<T> objects, final Integer size);

    /**
     * 使用SQL语句执行批量插入
     *
     * @param sql
     * @param values
     */
    public void batchInsertBySQL(final String sql, final List<Object[]> values);

    /**
     * 使用HQL查询返回MAP
     *
     * @param HQL
     * @param startRow
     * @param pageSize
     * @return
     */
    public List<Map> getMapByHQL(final String HQL, final Integer startRow, final Integer pageSize);

    /**
     * 使用HQL查询返回List
     *
     * @param HQL
     * @param startRow
     * @param pageSize
     * @return
     */
    public List<List> getListByHQL(final String HQL, final Integer startRow, final Integer pageSize);

    /**
     * 使用SQL查询返回List,List中存放对象
     *
     * @param SQL
     * @return
     */
    public <T> List<T> getListBySQL(final String SQL);

    /**
     * 使用SQL查询返回List,List中存放结果集数组
     *
     * @param SQL
     * @return
     */
    public List<Object[]> getListObjBySQL(final String SQL);

    /**
     * 使用SQL查询返回MAP
     *
     * @param SQL
     * @return
     */
    public <T> List<Map> getMapBySQL(final String SQL);

    /**
     * 模糊查询
     *
     * @param object   模糊查询对象
     * @param startRow 开始行数
     * @param pageSize 每页条数
     * @param <T>      泛型
     * @return List<T>
     */
    public <T> List<T> findByCriteria(final T object, final Integer startRow, final Integer pageSize);

    /**
     * 模糊查询记录总数
     *
     * @param object
     * @param <T>
     * @return
     */
    public <T> Long findByCriteriaCount(final T object);

    /**
     * 此方法适用于需要返回对像和与对象有关联的其他对象
     *
     * @param SQL
     * @param addClazz
     * @return
     */
    public List findBySqlWithJoin(final String SQL, final List<List> addClazz, final Integer startRow, final Integer pageSize);

    /**
     * 此方法返回多个对象
     *
     * @param SQL
     * @param alias
     * @return
     */
    public List findMoreBeanBySql(final String SQL, final List<List> alias, final Integer startRow, final Integer pageSize);

    /**
     * 使用SQL查询非受管实体,一般指DTO
     *
     * @param SQL      sql语句
     * @param claz     返回对象的类
     * @param startRow 起始数据
     * @param pageSize 获取数据量,大于0将使用分页,否则不会使用分页
     * @return List
     */
    public <T> List<T> getListBySQL(final String SQL, final Class<T> claz, final Integer startRow, final Integer pageSize);

    /**
     * 执行SQL语句
     *
     * @param sql sql语句
     */
    public void excudeSQL(final String sql);

    /**
     * 使用SQL查询单实体链表,不需要分页时使用
     *
     * @param sql sql语句
     * @param <T>
     * @return
     */
    public <T> List<T> findEntityBySQL(final String sql, final Class<T> clas);

    /**
     * 使用SQL查询单实体链表,分页时使用
     *
     * @param sql      sql语句
     * @param clas     查询实体类
     * @param startRow 开始记录
     * @param pageSize 分页大小
     * @param <T>
     * @return List
     */
    public <T> List<T> findEntityBySQL(final String sql, final Class<T> clas, final Integer startRow, final Integer pageSize);
}


DAO抽象类:
package com.blog.dao;


import org.apache.log4j.Logger;
import org.hibernate.*;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate4.SessionFactoryUtils;

import javax.annotation.Resource;
import javax.persistence.Table;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Iterator;
import java.lang.reflect.ParameterizedType;

/**
 * 功能:实现dao接口
 * Author: DR.YangLong
 * Date: 14-1-15
 * Time: 下午4:53
 * Email:[email protected]
 */
@SuppressWarnings({"unchecked"})
public abstract class SupperBaseDAOImp<T> implements SupperBaseDAO<T> {
    private Class<T> clazz;
    @Resource(name = "sessionFactory")
    protected SessionFactory sessionFactory;
    protected static Logger logger = Logger.getLogger(SupperBaseDAOImp.class);

    /**
     * 构造方法,构造时得到泛型对应的类
     */
    public SupperBaseDAOImp() {
        super();
        this.clazz = null;
        this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    @Override
    public void clean() {
        sessionFactory.getCurrentSession().clear();
    }

    @Override
    public void flush() {
        sessionFactory.getCurrentSession().flush();
    }

    /**
     * 提交数据并清空缓存
     */
    @Override
    public void flushANDclear() {
        sessionFactory.getCurrentSession().flush();
        sessionFactory.getCurrentSession().clear();
    }

    /**
     * 保存
     *
     * @param object 需要保存的对象
     * @return 保存成功的对象
     */
    @Override
    public Serializable save(final T object) {
        return sessionFactory.getCurrentSession().save(object);
    }

    /**
     * 更新
     *
     * @param object 需要更新的对象,必须包含ID及非空约束的列值(新值/旧值)
     */
    @Override
    public void update(final T object) {
        sessionFactory.getCurrentSession().update(object);
    }

    /**
     * 删除对象,物理删除
     *
     * @param object 需要删除的对象,必须包含ID及非空约束的列值
     */
    @Override
    public void delete(final T object) {
        sessionFactory.getCurrentSession().delete(object);
    }

    /**
     * 用sql根据id删除对象
     * spring3后版本
     *
     * @param id id
     */
    @Override
    public void delete(final Serializable id) {
        Annotation[] annotations = clazz.getAnnotations();
        String tableName = "";
        for (Annotation annotation : annotations) {
            if (annotation instanceof Table) {
                tableName = ((Table) annotation).name();
            }
        }
        if (tableName != null && tableName != "") {
            SQLQuery sqlQuery = sessionFactory.getCurrentSession().createSQLQuery("delete from " + tableName + " where id=?");
            sqlQuery.setInteger(0, (Integer) id);
            sqlQuery.executeUpdate();
        }
    }


//    **
//     * 用sql根据id删除对象
//     * spring3前版本
//     * @param id id
//     *
//    @Override
//    public void delete(final Serializable id) {
//        //通过反射,获取注解数组,再获取table注解,最终获取表名
//        Annotation[] annotations = clazz.getAnnotations();
//        for (Annotation annotation : annotations) {
//            //判断注解是否是@Table,如果是,则获取表名,执行删除
//            if (annotation instanceof Table) {
//                //获取注解中name属性的值
//                final String tableName = ((Table) annotation).name();
//                System.out.print(tableName);
//                //执行sql删除
//                HibernateTemplate hibernateTemplate = getHibernateTemplate();
//                hibernateTemplate.execute(new HibernateCallback<Object>() {
//                    @Override
//                    public Object doInHibernate(Session session)
//                            throws HibernateException, SQLException {
//                        session.doWork(new Work() {
//                            @Override
//                            public void execute(Connection conn) throws SQLException {
//                                PreparedStatement preparedStatement = conn
//                                        .prepareStatement("delete from " + tableName + " where id=?");
//                                preparedStatement.setInt(1, (Integer) id);
//                                preparedStatement.execute();
//                            }
//                        });
//                        return null;
//                    }
//                });
//            }
//        }
//    }

    /**
     * @param id  记录ID
     * @param <T> 泛型
     * @return T
     */
    @Override
    public <T> T findById(final Serializable id) {
        return (T) sessionFactory.getCurrentSession().get(clazz, id);
    }

    /**
     * load方式加载对象,先在对象管理池(2级缓存)中查找有没有对象,没有再创建代理,当使用的时候再查询数据库
     *
     * @param id  ID
     * @param <T> 泛型
     * @return T
     */
    @Override
    public <T> T loadById(final Serializable id) {
        return (T) sessionFactory.getCurrentSession().load(clazz, id);
    }

    /**
     * 利用唯一属性获取对象,错误则返回null
     *
     * @param propertyName 属性名称
     * @param value        属性值
     * @param <T>          泛型
     * @return T
     */
    @Override
    public <T> T findByProperty(final String propertyName, final Object value) {
        if (propertyName != null && value != null) {
            String clazzName = clazz.getSimpleName();
            StringBuffer stringBuffer = new StringBuffer("select obj from ");
            stringBuffer.append(clazzName).append(" obj");
            stringBuffer.append(" where obj.").append(propertyName).append("=:value");
            Query query = sessionFactory.getCurrentSession().createQuery(stringBuffer.toString()).setParameter("value", value);
            return (T) query.uniqueResult();
        }
        return null;
    }

    /**
     * 根据属性值对获取唯一对象,属性值对必须是数据库唯一,错误则返回null
     *
     * @param propertyNames 属性名称数组
     * @param values        属性值数组
     * @param <T>           泛型
     * @return T
     */
    @Override
    public <T> T findByProperties(final String[] propertyNames, final Object[] values) {
        if (propertyNames.length != 0 && values.length != 0 && propertyNames.length == values.length) {
            String clazzName = clazz.getSimpleName();
            StringBuffer stringBuffer = new StringBuffer("select Object(obj) from ");
            stringBuffer.append(clazzName);
            Query query = DaoUtil.createConditionQuery(sessionFactory, stringBuffer, propertyNames, values, "id", false);
            //执行查询
            return (T) query.uniqueResult();
        }
        return null;
    }

    /**
     * 使用实例对象获得持久记录
     *
     * @param object 对象
     * @param <T>    泛型
     * @return 对象
     */
    @Override
    public <T> T findByEntity(T object) throws IllegalAccessException {
        Map<String, Object> map = DaoUtil.getBeanPropertiesAndValues(object);
        //转换map为属性名数组和值数组
        List<Object[]> mapList = DaoUtil.changeMapToArray(map);
        String[] propertyNames = (String[]) mapList.get(0);
        Object[] values = (Object[]) mapList.get(1);
        //组装HQL
        StringBuffer stringBuffer = new StringBuffer("select obj from ").append(object.getClass().getSimpleName());
        DaoUtil.fillParameters(stringBuffer, propertyNames);
        //填充参数值
        Query query = DaoUtil.fillValues(sessionFactory, stringBuffer, propertyNames, values);
        //返回链表
        return (T) query.uniqueResult();
    }

    /**
     * @param <T> 泛型
     * @return List<T>
     */
    @Override
    public <T> List<T> findAll() {
        return sessionFactory.getCurrentSession().createQuery("from " + clazz.getSimpleName() + " obj").list();
    }

    public <T> List<T> findAllByPage(final String propertyName,final boolean desc,final Integer startRow,final Integer pageSize){
        String o=desc?"desc":"asc";
        return sessionFactory.getCurrentSession().createQuery("from "+clazz.getSimpleName()+" obj order by obj."+propertyName+" "+o).setFirstResult(startRow).setMaxResults(pageSize).list();
    }

    /**
     * 获取记录行数
     *
     * @return Long
     */
    @Override
    public Long findAllCount() {
        return ((BigInteger) sessionFactory.getCurrentSession().createSQLQuery("select count(0) from " + DaoUtil.getTableName(clazz)).uniqueResult()).longValue();
    }

    /**
     * 用iterator方式查询数据库
     *
     * @param <T> 泛型
     * @return Iterator
     */
    @Override
    public <T> List<T> findAllIterator() {
        int length = Integer.valueOf(this.findAllCount().toString());
        List<T> list = new ArrayList(length);
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery("from " + clazz.getSimpleName() + " obj");
        Iterator iterator = query.iterate();
        while (iterator.hasNext()) {
            list.add((T) iterator.next());
        }
        return list;
    }

    /**
     * 用HQL Iterator分页查询
     *
     * @param HQL      HQL查询语句
     * @param startRow 开始行数
     * @param pageSize 页码
     * @param <T>      泛型
     * @return List
     */
    @Override
    public <T> List<T> batchGetDataIteratorByHQL(final String HQL, final Integer startRow, final Integer pageSize) {
        Query query = sessionFactory.getCurrentSession().createQuery(HQL);
        query.setFirstResult(startRow);
        query.setMaxResults(pageSize);
        Iterator iterator = query.iterate();
        List<T> list = new ArrayList(pageSize);
        while (iterator.hasNext()) {
            list.add((T) iterator.next());
        }
        return list;
    }

    /**
     * 用HQL Srcoll查询
     * 大量查询时获取较高性能,此查询依赖于游标,返回的数据为查询的行值数组(Object[])
     * 可用于多表联合查询
     *
     * @param HQL      HQL查询语句
     * @param startRow 起始行
     * @param pageSize 要查询多少行
     * @return ScrollableResults
     */
    @Override
    public ScrollableResults batchGetDataScrollByHQL(final String HQL, final Integer startRow, final Integer pageSize) {
        Query query = sessionFactory.getCurrentSession().createQuery(HQL).setFirstResult(startRow).setMaxResults(pageSize);
        return query.scroll(ScrollMode.SCROLL_SENSITIVE);
    }

    /**
     * 用SQL Scroll查询,ScrollableResults取值时只能用get(int)取出Object然后强转型
     *
     * @param SQL      SQL查询语句
     * @param startRow 起始行
     * @param pageSize 要查询多少行
     * @return ScrollableResults
     */
    @Override
    public ScrollableResults batchGetDataScrollBySQL(final String SQL, final Integer startRow, final Integer pageSize) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(SQL).setFirstResult(startRow).setMaxResults(pageSize);
        ScrollableResults scrollableResults = query.scroll(ScrollMode.SCROLL_SENSITIVE);
        return scrollableResults;
    }

    /**
     * @param HQL HQL语句
     * @return Long
     */
    @Override
    public Long findCountByHQL(final String HQL) {
        if (HQL.contains("count")) {
            final int fromIndex = HQL.indexOf("from");
            final int commaIndex = HQL.indexOf(',');
            //如果from前面出现',',非法的HQL语句
            if (commaIndex!=-1&&fromIndex>commaIndex)
                return 0l;
            else return (Long) sessionFactory.getCurrentSession().createQuery(HQL).uniqueResult();
        } else {
            return 0l;
        }
    }

    /**
     * @param SQL sql语句
     * @return Long
     */
    @Override
    public Long findCountBySQL(final String SQL) {
        if (SQL.contains("count")) {
            String sql = SQL.toLowerCase();
            final int fromIndex = sql.indexOf("from");
            final int commaIndex = sql.indexOf(',');
            //如果from前面出现',',非法的SQL语句
            if (commaIndex!=-1&&fromIndex>commaIndex) return 0l;
              else{
                BigInteger bg = (BigInteger) sessionFactory.getCurrentSession().createSQLQuery(SQL).uniqueResult();
                return bg.longValue();
            }

        } else {
            return 0l;
        }
    }

    /**
     * 属性名称和属性值键值对数组形式查询对象链表
     *
     * @param propertyNames 属性名称数组
     * @param values        属性值数组
     * @param startRow      记录开始行数
     * @param pageSize      分页数(要取的记录行数)
     * @param <T>           泛型
     * @return List<T> or null
     */
    @Override
    public <T> List<T> findByProperty(final String[] propertyNames, final Object[] values, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isAsc) {
        if (propertyNames.length != 0 && values.length != 0 && propertyNames.length == values.length) {
            String clazzName = clazz.getSimpleName();
            StringBuffer stringBuffer = new StringBuffer("select Object(obj) from ");
            stringBuffer.append(clazzName);
            Query query = DaoUtil.createConditionQuery(sessionFactory, stringBuffer, propertyNames, values, sortColumn, isAsc);
            //分页
            query.setFirstResult(startRow);
            query.setMaxResults(pageSize);
            //执行查询
            return query.list();
        }
        return null;
    }







    /**
     * 只适用于基础数据类型属性,封装为HQL语句查询
     *
     * @param propertyNames 属性数组名称
     * @param values        属性值数组
     * @return Long
     */
    @Override
    public Long findByPropertyCount(final String[] propertyNames, final Object[] values) {
        if (propertyNames.length != 0 && values.length != 0 && propertyNames.length == values.length) {
            String clazzName = clazz.getSimpleName();
            StringBuffer stringBuffer = new StringBuffer("select count(0) from ");
            stringBuffer.append(clazzName);
            Query query = DaoUtil.createConditionQuery(sessionFactory, stringBuffer, propertyNames, values, "id", true);
            return (Long) query.uniqueResult();
        }
        return 0l;
    }

    /**
     * @param propertyName 属性名称
     * @param value        属性值
     * @param startRow     开始行数
     * @param pageSize     最大页数
     * @param sortColumn   排序字段
     * @param isAsc       是否升序
     * @param <T>          泛型
     * @return List<T>
     */
    @Override
    public <T> List<T> findByProperty(final String propertyName, final Object value, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isAsc) {
        String clazzName = clazz.getSimpleName();
        StringBuffer stringBuffer = new StringBuffer("select obj from ");
        stringBuffer.append(clazzName);
        Query query = DaoUtil.createSingleConditionHqlQuery(sessionFactory, stringBuffer, propertyName, value, sortColumn, isAsc);
        //分页
        query.setFirstResult(startRow);
        query.setMaxResults(pageSize);
        return query.list();
    }

    /**
     * 获取记录行数,封装为HQL语句查询
     *
     * @param propertyName 属性名称
     * @param value        属性值
     * @return 记录行数
     */
    @Override
    public Long findByPropertyCount(final String propertyName, final Object value) {
        String clazzName = clazz.getSimpleName();
        StringBuffer stringBuffer = new StringBuffer("select count(0) from ");
        stringBuffer.append(clazzName);
        Query query = DaoUtil.createSingleConditionHqlQuery(sessionFactory, stringBuffer, propertyName, value, "id", true);
        return (Long) query.uniqueResult();
    }

    /**
     * 用对象自动判断非空属性查询
     *
     * @param object     对象
     * @param startRow   开始行数
     * @param pageSize   每页数据
     * @param sortColumn 排序字段
     * @param isAsc     是否升序
     * @param <T>        泛参数
     * @return 列表
     */
    @Override
    public <T> List<T> findByProperty(final T object, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isAsc) {
        List list = null;
        try {
            Map<String, Object> map = DaoUtil.getBeanPropertiesAndValues(object);
            //转换map为属性名数组和值数组
            List<Object[]> mapList = DaoUtil.changeMapToArray(map);
            String[] propertyNames = (String[]) mapList.get(0);
            Object[] values = (Object[]) mapList.get(1);
            //组装HQL
            StringBuffer stringBuffer = new StringBuffer("select obj from ").append(clazz.getSimpleName());
            DaoUtil.fillParameters(stringBuffer, propertyNames);
            //排序
            String desc = isAsc ? "asc" : "desc";
            stringBuffer.append("order by obj.").append(sortColumn).append(" " + desc);
            //填充参数值
            Query query = DaoUtil.fillValues(sessionFactory, stringBuffer, propertyNames, values);
            //返回链表
            list = query.list();
            return list;
        } catch (IllegalAccessException e) {
            logger.info("抛出异常方法:getBeanPropertiesAndValues!调用方法:SupperBaseDAOImp.findByProperty()");
            e.printStackTrace();
        }
        return list;
    }



    /**
     * @param object 根据对象查询记录数量
     * @return Long
     */
    @Override
    public Long findByPropertyCount(final T object) {
        long count;
        try {
            Map<String, Object> map = DaoUtil.getBeanPropertiesAndValues(object);
            //转换map为属性名数组和值数组
            List<Object[]> mapList = DaoUtil.changeMapToArray(map);
            String[] propertyNames = (String[]) mapList.get(0);
            Object[] values = mapList.get(1);
            //组装HQL
            StringBuffer stringBuffer = new StringBuffer("select obj from ").append(clazz.getSimpleName());
            DaoUtil.fillParameters(stringBuffer, propertyNames);
            //填充参数值
            Query query = DaoUtil.fillValues(sessionFactory, stringBuffer, propertyNames, values);
            //返回链表
            count = (Long) query.uniqueResult();
            return count;
        } catch (IllegalAccessException e) {
            logger.info("抛出异常方法:getBeanPropertiesAndValues!调用方法:SupperBaseDAOImp.findByPropertyCount()");
            e.printStackTrace();
        }
        return 0l;
    }

    /**
     * 用Map参数分页查询记录
     *
     * @param map        map<String propertyName,Object value>
     * @param startRow   记录开始行数
     * @param pageSize   获取记录数
     * @param sortColumn 排序字段
     * @param isAsc     是否升序
     * @param <T>        泛型
     * @return List<T>
     */
    @Override
    public <T> List<T> findByProperty(final Map<String, Object> map, final Integer startRow, final Integer pageSize, final String sortColumn, final boolean isAsc) {
        List<Object[]> mapList = DaoUtil.changeMapToArray(map);
        String[] propertyNames = (String[]) mapList.get(0);
        Object[] values = mapList.get(1);
        StringBuffer stringBuffer = new StringBuffer("select obj from ").append(clazz.getSimpleName());
        Query query = DaoUtil.createConditionQuery(sessionFactory, stringBuffer, propertyNames, values, sortColumn, isAsc);
        query.setFirstResult(startRow);
        query.setMaxResults(pageSize);
        return query.list();
    }

    /**
     * 用Map参数分页查询记录数,封装为HQL查询
     *
     * @param map map<String propertyName,Object value>
     * @return Long
     */
    @Override
    public Long findByPropertyCount(final Map<String, Object> map) {
        List<Object[]> mapList = DaoUtil.changeMapToArray(map);
        String[] propertyNames = (String[]) mapList.get(0);
        Object[] values = mapList.get(1);
        StringBuffer stringBuffer = new StringBuffer("select count(0) from ").append(clazz.getSimpleName());
        Query query = DaoUtil.createConditionQuery(sessionFactory, stringBuffer, propertyNames, values, "id", true);
        return (Long) query.uniqueResult();
    }

    /**
     * 使用sql语句查询记录
     *
     * @param sql    sql语句,参数位置用?代替
     * @param values 不定数参数
     * @param <T>    泛型
     * @return List<T>
     */
    @Override
    public <T> List<T> findBySql(final String sql, final Object... values) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(sql).addEntity(clazz);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        return query.list();
    }

    /**
     * @param sql    sql语句
     * @param values 值
     * @return Long记录数
     */
    @Override
    public Long findBySqlCount(final String sql, final Object... values) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(sql);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        long count = ((BigInteger) query.uniqueResult()).longValue();
        return count;
    }

    /**
     * 查询外键后会创建代理对象,可以使用get方法获取对应的关联对象
     *
     * @param sql    SQL语句
     * @param values 不定长参数
     * @param <T>    泛型
     * @return 单个对象
     */
    @Override
    public <T> T findUniqueBySql(final String sql, final Object... values) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(sql).addEntity(clazz);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        return (T) query.uniqueResult();
    }

    /**
     * 使用sql语句批量删除或更新
     *
     * @param sql    sql语句
     * @param values 参数值
     * @return 影响行数
     */
    @Override
    public int batchUpdateOrDelete(final String sql, final Object... values) {
        //是否是合法的sql插入语句
        if (sql.indexOf("update") != -1) {
            Query query = sessionFactory.getCurrentSession().createSQLQuery(sql);
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i, values[i]);
            }
            //设置忽略二级缓存
            query.setCacheMode(CacheMode.IGNORE);
            query.setCacheable(false);
            return query.executeUpdate();
        }
        return 0;
    }

    /**
     * HQL批量插入,本方法线程同步且打开新的数据库连接
     *
     * @param objects 插入对象List
     * @param size    每插入多少条记录清空缓存
     */
    @Override
    public synchronized void batchInsertByHQL(List<T> objects, Integer size) {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        //设置不二级缓存
        session.setCacheMode(CacheMode.IGNORE);
        int i = 0;
        final int length = objects.size();
        while (i < length) {
            session.save(objects.get(i));
            i++;
            if (i % size == 0) {
                session.flush();
                session.clear();
            }
        }
        tx.commit();
        session.close();
    }

    /**
     * SQL语句批量插入,采用预定义SQL,Preparedstatement,传入需插入的值链表,其中每个字符串数组对应一条记录
     * prepareStatement设置参数从1开始,createQuery,createSQLQuery设置参数从0开始
     *
     * @param sql    插入语句,如:insert into user_info(account,pwd) values
     * @param values 需插入数据库值
     */
    @Override
    public void batchInsertBySQL(final String sql, final List<Object[]> values) {
        final int length = values.get(0).length;
        if (length != 0) {
            try {
                StringBuffer stringBuffer = new StringBuffer(sql);
                final int size = values.size();
                //拼接values后的括号和参数位
                for (int i = 0; i < size; i++) {
                    stringBuffer.append("(");
                    for (int j = 0; j < length; j++) {
                        if (j == 0) stringBuffer.append("?");
                        if (j != 0) stringBuffer.append(",?");
                    }
                    if (i != size - 1) stringBuffer.append("),");
                    if (i == size - 1) stringBuffer.append(")");
                }
                //生成预处理SQL
                Connection conn = SessionFactoryUtils.getDataSource(sessionFactory).getConnection();
                PreparedStatement statement = conn.prepareStatement(stringBuffer.toString());
                int len = size;
                List<Object> list = new ArrayList(size * length);
                //获取所有参数
                int loopI = 0;
                while (len > loopI) {
                    Object[] objects = values.get(loopI);
                    for (int i = 0; i < length; i++) {
                        list.add(objects[i]);
                    }
                    loopI++;
                }
                int listLen = list.size();
                int index = 1;
                //填充参数
                while (index <= listLen) {
                    statement.setObject(index, list.get(index - 1));
                    index++;
                }
                statement.addBatch();
                statement.executeBatch();
            } catch (SQLException e) {
                e.printStackTrace();
                logger.info("##com.blog.dao.SupperBaseDAOImp.batchInsertBySQL(final String sql, final List<Object[]> values)方法出错##");
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
                logger.info("##com.blog.dao.SupperBaseDAOImp.batchInsertBySQL(final String sql, final List<Object[]> values)方法出错##");
            }
        }
    }

    /**
     * the table data with sql:"select d.code,d.value from dictionary d":
     * +------+--------+
     * | code | value  |
     * +------+--------+
     * | 001  | 四川   |
     * | 002  | 北京   |
     * | 001  | 四川   |
     * +------+--------+
     * eg:select new Map(d.code, d.value) from Dictionary d
     * result:[{0=001,1=四川},{0=002,1=北京},{0=001,1=四川}]
     * the result is List<Map>,one Map is one record,if not define the alias name,the map's key will be the column index and start with 0;
     * if you define a alias name ,it to be like this:
     * select new Map(d.value as value, d.code as code) from Dictionary d
     * [{value=四川, code=001},{value=北京, code=002},{value=四川, code=001}]
     * select new Map(d.value, d.code as code) from Dictionary d
     * [{0=四川, code=001},{0=北京, code=002},{0=四川, code=001}]
     * the map's key will be the alias name!
     *
     * @param HQL      HQL语句,如:select new Map(d.code as code, d.value as value) from Dictionary d;标明别名的‘as’是必须的
     * @param startRow 开始行数
     * @param pageSize 返回记录数
     * @return List<Map>
     */
    @Override
    public List<Map> getMapByHQL(final String HQL, final Integer startRow, final Integer pageSize) {
        Query query = sessionFactory.getCurrentSession().createQuery(HQL).setFirstResult(startRow).setMaxResults(pageSize);
        return query.list();
    }

    /**
     * table data:
     * +----+------+--------+
     * | id | code | value  |
     * +----+------+--------+
     * |  1 | 001  | 四川   |
     * |  2 | 002  | 北京   |
     * |  3 | 001  | 四川   |
     * +----+------+--------+
     * eg:select new List(d.code,d.value) from Dictionary d
     * result:[[001, 四川], [002, 北京], [001, 四川]]
     * the result is List<List>, one inner list is filled by column's value using one record
     *
     * @param HQL      HQL语句
     * @param startRow 开始行数
     * @param pageSize 返回记录数
     * @return List<List>
     */
    @Override
    public List<List> getListByHQL(final String HQL, final Integer startRow, final Integer pageSize) {
        Query query = sessionFactory.getCurrentSession().createQuery(HQL).setFirstResult(startRow).setMaxResults(pageSize);
        return query.list();
    }

    /**
     * 通过SQL语句查询记录,如果换addEntity使用query.addScalar(String,Hibernate.xxx)会产生List<Object[]>,且只返回addScalar声明过的字段
     * 此方法要求SQL语句中的返回列名称与实体属性名称匹配且等于或少于实体属性数量,此方法局限于:只能返回对应类本身的简单属性,不能返回类属性
     *
     * @param SQL sql语句
     * @return List<T>
     */
    @Override
    public <T> List<T> getListBySQL(final String SQL) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(SQL).addEntity(clazz);
        return query.list();
    }

    /**
     * 使用SQL查询非受管实体,一般指DTO
     * @param SQL sql语句
     * @param claz 返回对象的类
     * @param startRow 起始数据
     * @param pageSize 获取数据量,大于0将使用分页,否则不会使用分页
     * @return List
     */
    public <T> List<T> getListBySQL(final String SQL,final Class<T> claz,final Integer startRow,final Integer pageSize){
        Query query = sessionFactory.getCurrentSession().createSQLQuery(SQL).setResultTransformer(Transformers.aliasToBean(claz));
       if(pageSize>0) {
           query.setFirstResult(startRow).setMaxResults(pageSize);
       }
       return query.list();
    }

    /**
     * SQL查询返回List,List中存放的是Object数组,每个数组对应一条记录,数组的索引对应查询返回的列的索引(从0开始)
     *
     * @param SQL sql语句
     * @return List<Object[]>
     */
    @Override
    public List<Object[]> getListObjBySQL(String SQL) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(SQL);
        return query.list();
    }

    /**
     * 通过SQL查询记录,一个map是一个记录,Map的Key是查询出来的column的名称,值为对应记录的值
     *
     * @param SQL sql语句
     * @return List<Map>
     */
    @Override
    public List<Map> getMapBySQL(String SQL) {
        Query query = sessionFactory.getCurrentSession().createSQLQuery(SQL).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return query.list();
    }

    /**
     * 用SQL查询返回当前泛型对应实体对象,只返回一种类对应实体对象列表,包含子/关联实体
     * SQL需要视情况使用别名注入
     * 例如:
     * 一对一
     * createSQLQuery("select {login.*},{user.*} from user_login login,user_info user where user.loginid=login.id and loginid=1").addEntity("lgonin",UserLogin.class).addJoin("user","login.userInfo").list();
     * 一对多:
     * createSQLQuery("select {ar.*},{ca.*} from article_category ca,article_content ar where ar.category=ca.id").addEntity("ca",ArticleCategory.class).addJoin("ar","ca.articleContents").list();
     * 将会返回List<Object[]>,每个Object[]中有一个UserLogin(ArticleCategory)和一个UserInfo(ArticleContent)对象[其中ArticleCategory中的一对多关联的SET集合被初始化],亦即是说关联会多产生被关联对象,Object[0]中的对象永远是addEntity中类的对象,List.size=记录的条数,即一对一时:多少条记录对应size;多对多时:多的一方记录条数对应size。
     *
     * @param addClazz List<List<Object>>,第一个inner List放返回的对象的别名和类,接着的放关联对象的别名和类
     * @param startRow 开始行数
     * @param pageSize 取记录数量 当此量大于0时才会调用Hibernate的分页功能
     * @return List
     */
    @Override
    public List findBySqlWithJoin(final String SQL, final List<List> addClazz, final Integer startRow, final Integer pageSize) {
        List ls = addClazz.get(0);
        Class claz = (Class) ls.get(1);
        SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery(SQL).addEntity((String) ls.get(0), claz);
        //如果需要关联
        if(addClazz.size()>1) {
            List join = addClazz.subList(1, addClazz.size());
            for (int i = 0; i < join.size(); i++) {
                List sub = (List) join.get(i);
                query.addJoin((String) sub.get(0), (String) sub.get(1));
            }
        }
        if (startRow >= 0 && pageSize > 0) {
            query.setFirstResult(startRow);
            query.setMaxResults(pageSize);
        }
        return query.list();
    }



    /**
     * 查询多个实体,必须包含全字段
     * createSQLQuery("select {ar.*},{ca.*} from article_category ca,article_content ar where ar.id=ca.id").addEntity("ca",ArticleCategory.class).addEntity("ar",ArticleContents.class).list();
     * 将会返回List<Object[]>,每个Object[]中有一个ArticleCategory和一个ArticleContent对象[其中ArticleCategory中的一对多关联的SET集合被初始化],亦即是说关联会多产生被关联对象,
     * Object[0]中的对象永远是第一个addEntity中类的对象,List.size=查询到的记录的条数。
     *
     * @param SQL      SQL语句,可包含分页信息,如果不要分页pageSize要设为<=0
     * @param alias    类名参数数组
     * @param startRow 记录开始行数
     * @param pageSize 获取记录数量
     * @return List
     */
    @Override
    public List findMoreBeanBySql(final String SQL, final List<List> alias, final Integer startRow, final Integer pageSize) {
        SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery(SQL);
        //添加实体
        for (int i = 0; i < alias.size(); i++) {
            List sub = alias.get(i);
            query.addEntity((String) sub.get(0), (Class) sub.get(1));
        }
        if (startRow > 0 && pageSize > 0) {
            query.setFirstResult(startRow);
            query.setMaxResults(pageSize);
        }
        return query.list();
    }

    @Override
    public void excudeSQL(final String sql) {
        sessionFactory.getCurrentSession().createSQLQuery(sql).executeUpdate();
    }

    @Override
    public <T> List<T> findObjsByHQL(final String HQL, final Integer startRow, final Integer pageSize) {
        return sessionFactory.getCurrentSession().createQuery(HQL).setFirstResult(startRow).setMaxResults(pageSize).list();
    }
    @Override
    public <T>List<T> findEntityBySQL(final String sql,final Class<T> clas){
        return sessionFactory.getCurrentSession().createSQLQuery(sql).addEntity(clas).list();
    }

    @Override
    public <T> List<T> findEntityBySQL(String sql, Class<T> clas, Integer startRow, Integer pageSize) {
        return sessionFactory.getCurrentSession().createSQLQuery(sql).addEntity(clas).setFirstResult(startRow).setMaxResults(pageSize).list();
    }
}


DAO辅助类:
package com.blog.dao;

import com.blog.common.exception.ArrayNoBallenceException;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;

import javax.persistence.Column;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 功能或描述:dao辅助类,提供一些通用功能
 *
 * @Author: DR.YangLong
 * @Date: 14-6-17
 * @Time: 上午11:47
 * @Email: [email protected]
 * @Version: 1.0
 * @Module: 修正:            日期:
 */
public class DaoUtil {
    protected static Logger logger = Logger.getLogger(DaoUtil.class);
    /**
     * 获取对象对应的表名
     *
     * @param object 需获取表名对象
     * @return 类对应的表名
     */
    public static String getTableName(final Object object) {
        Annotation[] annotations = object.getClass().getAnnotations();
        String tableName = "";
        for (Annotation annotation : annotations) {
            if (annotation instanceof Table) {
                tableName = ((Table) annotation).name();
            }
        }
        return tableName;
    }

    /**
     * 获取当前类对应的数据表名称
     *
     * @return 表名称
     */
    public static String getTableName(Class clazz) {
        Annotation[] annotations = clazz.getAnnotations();
        String tableName = "";
        for (Annotation annotation : annotations) {
            if (annotation instanceof Table) {
                tableName = ((Table) annotation).name();
            }
        }
        return tableName;
    }

    /**
     * 获取类的所有属性名称
     *
     * @param clazz 类
     * @return 属性名称数组
     */
    public static String[] getClassPropertiesNames(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        final int length = fields.length;
        String[] columnNames = new String[length];
        for (int i = 0; i < length; i++) {
            columnNames[i] = fields[i].getName();
        }
        return columnNames;
    }

    /**
     * 获取对象的属性名称数组
     *
     * @param object 需获取属性名称的对象
     * @return 属性名称
     */
    public static String[] getBeanProperties(final Object object) {
        //获取Object对应的类中的所有属性名称,不包含继承
        Class clazz = object.getClass();
        return DaoUtil.getClassPropertiesNames(clazz);
    }

    /**
     * 获取类对应的表的字段名称
     *
     * @param clazz 类
     * @return 字段名称数组
     * @throws java.beans.IntrospectionException
     */
    public static String[] getClassTableColumnName(Class clazz) throws IntrospectionException {
        Field[] fields = clazz.getDeclaredFields();//get array of properties
        //loop fields to get getmethod annotation
        List<String> columnNames = new ArrayList();
        for (Field field : fields) {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), clazz);
            Method method = propertyDescriptor.getReadMethod();
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof Column) {
                    columnNames.add(((Column) annotation).name());
                }
                if (annotation instanceof JoinColumn) {
                    columnNames.add(((JoinColumn) annotation).name());
                }
            }
        }
        String[] names = new String[columnNames.size()];
        names = columnNames.toArray(names);
        return names;
    }

    /**
     * 获取对象的模板类对应的数据库表的字段名称数组
     *
     * @param object 对象
     * @return 字段数组
     * @throws IntrospectionException
     */
    public static String[] getBeanTableColumnNames(final Object object) throws IntrospectionException {
        Class clazz = object.getClass();
        return DaoUtil.getClassTableColumnName(clazz);
    }

    /**
     * 根据传入的StringBuffer和对称数组组装HQL语句query对象
     *
     * @param sessionFactory session工厂
     * @param stringBuffer  obj where前的查询语句
     * @param propertyNames 属性名数组
     * @param values        属性值数组
     * @param sortColumn    排序字段
     * @param isAsc        是升序
     * @return Query
     */
    public static Query createConditionQuery(SessionFactory sessionFactory,StringBuffer stringBuffer, final String[] propertyNames, final Object[] values, final String sortColumn, final boolean isAsc) {
        //生成带参数的HQL
        DaoUtil.fillParameters(stringBuffer, propertyNames);
        //排序
        String desc = isAsc ? "asc" : "desc";
        stringBuffer.append("order by obj.").append(sortColumn).append(" " + desc);
        //填充实参
        Query query = DaoUtil.fillValues(sessionFactory,stringBuffer, propertyNames, values);
        return query;
    }

    /**
     * 填充参数
     *
     * @param stringBuffer  obj where之前语句生成的stringBuffer
     * @param propertyNames 属性名称数组
     * @return StringBuffer
     */
    public static StringBuffer fillParameters(final StringBuffer stringBuffer, final String[] propertyNames) {
        stringBuffer.append(" obj where ");
        //生成带参数的HQL
        for (int i = 0; i < propertyNames.length; i++) {
            //第一个条件
            if (i == 0)
                stringBuffer.append("obj.").append(propertyNames[i]).append("=:").append(propertyNames[i] + " ");
            //第二个开始的条件
            if (i != 0)
                stringBuffer.append("and obj.").append(propertyNames[i]).append("=:").append(propertyNames[i] + " ");
        }
        //生成查询语句
        logger.info("组装的HQL:" + stringBuffer.toString());
        return stringBuffer;
    }

    /**
     * 填充实参
     *
     * @param sessionFactory session工厂
     * @param stringBuffer  HQL语句
     * @param propertyNames 属性名称数组
     * @param values        属性值数组
     * @return Query
     */
    public static Query fillValues( SessionFactory sessionFactory,final StringBuffer stringBuffer, final String[] propertyNames, final Object[] values) {
        Query query = sessionFactory.getCurrentSession().createQuery(stringBuffer.toString());
        //设置参数值
        final int n = propertyNames.length;
        for (int i = 0; i < n; i++) {
            query.setParameter(propertyNames[i], values[i]);
        }
        return query;
    }

    /**
     * 组装HQL语句,单属性值对,按指定字段排序
     *
     * @param stringBuffer obj where前的可变字符串
     * @param propertyName 属性名称
     * @param value        值
     * @param sortColumn   排序字段
     * @param isAsc       是否升序
     * @return Query
     */
    public static Query createSingleConditionHqlQuery(SessionFactory sessionFactory,StringBuffer stringBuffer, final String propertyName, final Object value, final String sortColumn, final boolean isAsc) {
        //组装HQL
        String desc = isAsc ? "asc" : "desc";
        stringBuffer.append(" obj where obj.").append(propertyName).append("=:").append(propertyName).append(" order by obj.").append(sortColumn).append(" " + desc);
        logger.info("组装的HQL:" + stringBuffer.toString());
        Query query = sessionFactory.getCurrentSession().createQuery(stringBuffer.toString());
        //设置参数
        query.setParameter(propertyName, value);
        return query;
    }

    /**
     * 获取对象的非空属性名称和属性值对应的map
     *
     * @param object 对象
     * @param <T>    泛型参数
     * @return map
     */
    public static <T> Map<String, Object> getBeanPropertiesAndValues(final T object) throws IllegalAccessException {
        //获取泛型对应的类中的所有属性名称
        Field[] fields = object.getClass().getDeclaredFields();
        Map<String, Object> map = new HashMap();
        Map<String, Object> returnMap = new HashMap();
        //获取属性名称和值对应的map
        for (Field field : fields) {
            //第一个属性名称
            String propertyName = field.getName();
            //获取属性的访问检查控制
            boolean isAccess = field.isAccessible();
            //取消访问检查以便可以通过反射获取属性值
            field.setAccessible(true);
            //获取属性值
            Object value = field.get(object);
            //放入map
            map.put(propertyName, value);
            //恢复访问检查控制
            field.setAccessible(isAccess);
        }
        Iterator iterator = map.keySet().iterator();
        //循环判断值是否为空
        while (iterator.hasNext()) {
            //获取键名称
            String keyName = (String) iterator.next();
            //获取非空值
            if (map.get(keyName) != null) {
                returnMap.put(keyName, map.get(keyName));
            }
        }
        return returnMap;
    }

    /**
     * 获取map中的键值数组对
     *
     * @param map MAP<String propertyName,Object value>
     * @return List<Object[]> length=2
     */
    public static List<Object[]> changeMapToArray(Map map) {
        //获取key集合
        Set keySet = map.keySet();
        //获取属性名称数组
        String[] propertyNames = new String[keySet.size()];
        propertyNames = (String[]) keySet.toArray(propertyNames);
        //获取属性名称对应的属性值
        final int length = propertyNames.length;
        Object[] values = new Object[length];
        for (int i = 0; i < length; i++) {
            values[i] = map.get(propertyNames[i]);
        }
        //返回数组对
        List<Object[]> list = new ArrayList();
        list.add(propertyNames);
        list.add(values);
        return list;
    }

    /**
     * 组装成List<List>,将obj数组按每组size个参数分组
     *
     * @param size inner List的长度
     * @param obj  不定长参数
     * @return List
     */
    public static List<List> assemblingList(final Integer size, final Object... obj) throws ArrayNoBallenceException {
        int length = obj.length;
        if (length % size != 0) {
            throw new ArrayNoBallenceException();
        } else {
            int outerLoop = obj.length / size;
            List<List> outerList = new ArrayList(outerLoop);
            for (int i = 0; i < outerLoop; i++) {
                List innerList = new ArrayList(size);
                for (int j = i; j < i + size; j++) {
                    innerList.add(obj[j]);
                }
                outerList.add(innerList);
            }
            return outerList;
        }
    }
}


使用示例,一个实现类:
@Repository
public class UserInfoDAOImp extends SupperBaseDAOImp<UserInfo> {
    @Override
    public <T> List<T> findByCriteria(final T object,final Integer startRow,final Integer pageSize) {
        return null;
    }

    @Override
    public <T> Long findByCriteriaCount(T object) {
        return null;
    }
}


测试用例,没有使用断言,而是打印:
package com.blog.dao;

import com.blog.daoImp.UserInfoDAOImp;
import com.blog.daoImp.UserLoginDAOImp;
import com.blog.dto.ArticleModel;
import com.blog.model.ArticleCategory;
import com.blog.model.ArticleContent;
import com.blog.model.UserInfo;
import com.blog.model.UserLogin;
import junit.framework.TestCase;
import org.hibernate.ScrollableResults;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
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 java.util.*;

/**
 * 功能:DAO测试
 * Author: DR.YangLong
 * Date: 14-1-16
 * Time: 下午2:52
 * Email:[email protected]
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring*.xml",
})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class DaoTest extends TestCase {
    @Autowired
    private UserLoginDAOImp supperBaseDAO;
    @Autowired
    private UserInfoDAOImp userInfoDAOImp;
    //private static Logger logger = Logger.getLogger(DaoTest.class);

    @Test
    @Transactional
    @Rollback(false)
    public void loginTest() {
//        for (int i = 0; i < 10; i++) {
//            UserLogin userLogin = new UserLogin();
//            userLogin.setAccount("wwwww" + i);
//            userLogin.setPwd("12345w678");
//            supperBaseDAO.save(userLogin);
//        }
//        System.out.println(userLogin.getId() + ":" + userLogin.getAccount() + ":" + userLogin.getPwd() + "!" + userLogin.getUserInfo().getId() + ":" + userLogin.getUserInfo().getNickname());
//          List<UserLogin> list=supperBaseDAO.findAll();
//          for(UserLogin userLogin:list){
//              System.out.println("账号:"+userLogin.getAccount());
//              System.out.println("密码:"+userLogin.getPwd());
//          }
        UserInfo userInfo = new UserInfo();
        userInfo.setComefrom("kunming");
        userInfo.setConstellation("射手座");
        userInfo.setGender("女");
        userInfo.setNickname("侧四");
        userInfo.setHeight(18.6);
        userInfo.setWeight(50.0);
        userInfo.setHobby("basketball");
        userInfo.setUsername("csshi");
        userInfo.setIntroduction("jieshao");
        userInfo.setProfession("码农");
        UserLogin userLogin = supperBaseDAO.findById(8);
        userInfo.setUserLogin(userLogin);
        userInfoDAOImp.save(userInfo);
    }

    @Test
    @Transactional
    public void testLogin() {
        UserLogin userLogin = supperBaseDAO.findByProperties(new String[]{"account", "pwd"}, new Object[]{"wwww", "12345w678"});
        if (userLogin != null) {
            System.out.println("ID:" + userLogin.getId());
            System.out.println("账号:" + userLogin.getAccount());
            System.out.println("密码:" + userLogin.getPwd());
        } else {
            System.out.println("无记录!");
        }
    }
    @Test
    @Transactional
    public void testByProperty(){
        UserLogin userLogin = supperBaseDAO.findByProperty("id",1);
        System.out.println("用户名:"+userLogin.getAccount()+"/t 密码:"+userLogin.getPwd());
    }
    @Test
    @Transactional
    public void testCount() {
        System.out.println("HQL:" + supperBaseDAO.findCountByHQL("select count(0),obj.id from UserLogin obj"));
        System.out.println("SQL:" + supperBaseDAO.findCountBySQL("select count(0),id FROM user_login"));
    }

    @Test
    @Transactional
    public void testSingleCount() {
        long count = supperBaseDAO.findByPropertyCount("account", "test");
        System.out.println("测试单对属性值查询行数:" + count);
    }

    @Transactional
    @Test
    public void testSingleFindList() {
        List<UserLogin> list = supperBaseDAO.findByProperty("account", "test", 0, 17000, "id", true);
        System.out.println(list.size());
        for (UserLogin userLogin : list) {
            System.out.println("##" + userLogin.getId() + "##");
        }
    }

/*    @Test
    public void testGetProperty() {
        UserInfo userInfo= new UserInfo();
        userInfo.setComefrom("昆明");
        userInfo.setConstellation("天秤座");
        userInfo.setGender("男");
        try {
            Map map = supperBaseDAO.getBeanPropertiesAndValues(userInfo);
            Iterator it = map.keySet().iterator();
            while (it.hasNext()) {
                String key=(String)it.next();
                System.out.print("名称:" + key+"#");
                System.out.println("值:" + map.get
                        (key));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }*/

    @Test
    @Transactional
    public void testFindByObj() {
        UserLogin userLogin = new UserLogin();
        userLogin.setAccount("test");
        List<UserLogin> list = supperBaseDAO.findByProperty(userLogin, 0, 17000, "id", false);
        System.out.println(list.size());
        for (UserLogin usErLogin : list) {
            System.out.println("##" + usErLogin.getId() + "##");
        }
    }

    @Test
    @Transactional
    public void testFindByMap() {
        Map<String, Object> map = new HashMap();
        map.put("account", "test");
        List<UserLogin> list = supperBaseDAO.findByProperty(map, 0, 17000, "pwd", true);
        System.out.println(list.size());
        for (UserLogin usErLogin : list) {
            System.out.println("##" + usErLogin.getId() + "##");
        }
    }

    @Test
    @Transactional
    public void testListBySQL() {
        List<UserLogin> list = supperBaseDAO.getListBySQL("select * from user_login where account='test'");
        for (UserLogin usErLogin : list) {
            System.out.println("##" + usErLogin.getId() + "##");
        }
    }

    @Transactional
    @Test
    public void getListObjBySQL() {
        List list = supperBaseDAO.getListObjBySQL("select * from user_login where account='test' limit 0,5");
        System.out.println("长度:" + list.size());
        Object[] objects = (Object[]) list.get(0);
        for (Object o : objects) {
            System.out.println(o.toString());
        }


    }

    @Test
    @Transactional
    public void testMapBySQL() {
        List<Map> list = supperBaseDAO.getMapBySQL("select * from user_login limit 0,10");
        System.out.print("@@@@@@@@@@@@@@@@@");
        for (Map usErLogin : list) {
            System.out.println("##" + usErLogin.get("id") + "##" + usErLogin.get("account") + "##" + usErLogin.get("userInfo"));
        }
    }

    @Test
    @Transactional
    public void testFindBySql() {
        List<UserLogin> list = supperBaseDAO.findBySql("select * from user_login where account=? and pwd=? limit 0,10", "test", "testpwd");
        for (UserLogin usErLogin : list) {
            System.out.println("##" + usErLogin.getId() + "##");
        }
    }

    @Test
    @Transactional
    public void testFindBySqlCount() {
        System.out.println("##" + supperBaseDAO.findBySqlCount("select count(0) from user_login where account=? and pwd=?", "test", "testpwd") + "##");
    }

    @Test
    @Transactional
    public void findUniqueBySql() {
        UserLogin userLogin = supperBaseDAO.findUniqueBySql("select * from user_login where account=? and pwd=?", "test55", "testpwd");
        System.out.println("##" + userLogin.getId() + "##");
    }

    @Test
    @Transactional
    @Rollback(false)
    public void testbatchInsertBySQL() {
        String sql = "insert into user_login(account,pwd) values";
        List list = new ArrayList();
        for (int i = 0; i < 10000; i++) {
            Object[] objects = {"batchinsert", "batchinsert" + 50000 + i};
            list.add(objects);
            System.out.println(objects.toString());
        }
        supperBaseDAO.batchInsertBySQL(sql, list);
    }

    @Transactional
    @Test
    public void testbatchInsertByHQL() {
        List<UserLogin> lit = new ArrayList(100000);
        for (int i = 0; i < 40000; i++) {
            UserLogin userLogin = new UserLogin();
            userLogin.setAccount("save");
            userLogin.setPwd("hib" + i);
            lit.add(userLogin);
        }
        supperBaseDAO.batchInsertByHQL(lit, 50);
    }

    @Transactional
    @Test
    public void testHQLMap() {
        String HQL = "select new Map(u.id as id,u.account as account,u.pwd as pwd) from UserLogin as u where u.account='test'";
        List<Map> list = supperBaseDAO.getMapByHQL(HQL, 1, 10);
        for (Map map : list) {
            System.out.println("!!打印id:" + map.get("id") + "#打印account:" + map.get("account") + "#打印pwd:" + map.get("pwd") + "!!!");
        }
    }

    @Test
    @Transactional
    public void testHQLList() {
        String HQL = "select new List(u.id as id,u.account as account,u.pwd as pwd) from UserLogin as u where u.account='test'";
        List<List> list = supperBaseDAO.getListByHQL(HQL, 1, 10);
        for (List list1 : list) {
            System.out.println("!!打印id:" + list1.get(0) + "#打印account:" + list1.get(1) + "#打印pwd:" + list1.get(2) + "!!!");
        }
    }

    @Test
    @Transactional
    public void findAllIterator() {
        List<UserLogin> iterato = supperBaseDAO.findAllIterator();
        for (UserLogin userLogin : iterato) {
            System.out.println("ID:" + userLogin.getId() + "ACCOUNT:" + userLogin.getAccount() + "PASSWORD:" + userLogin.getPwd());
        }
    }

/*    @Test
    @Transactional
    @SuppressWarnings(value = "ALL")
    public void BeanTableNameColumns() {
        System.out.println("!!!!table!!!!!!!" + supperBaseDAO.getTableName());
        try {
            //String[] strs = supperBaseDAO.getBeanTableColumnNames(new ArticleContent());
            String[] strs = supperBaseDAO.getBeanTableColumnNames();
            for (String str : strs) {
                System.out.println("!!!!Column!!!!!!!" + str);
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
        System.out.println("!!!!table!!!!!!!" + supperBaseDAO.getTableName(new ArticleContent()));
        String[] strss = supperBaseDAO.getBeanProperties(new ArticleContent());
        for (String str : strss) {
            System.out.println("!!!!Property!!!!!!!" + str);
        }
    }*/

    @Test
    @Transactional
    public void testBatchIteratorHQL() {
        List<UserLogin> list = supperBaseDAO.batchGetDataIteratorByHQL("from UserLogin", 0, 5);
//      UserLogin userLogin=list.get(0);
//       System.out.println("ID:"+userLogin.getId()+"用户名:"+userLogin.getAccount()+"密码:"+userLogin.getPwd());
        for (UserLogin userLogin : list) {
            System.out.println("ID:" + userLogin.getId() + "用户名:" + userLogin.getAccount() + "密码:" + userLogin.getPwd());
        }

    }

    @Test
    @Transactional
    public void testBatchScroll() {
        ScrollableResults scrollableResults = supperBaseDAO.batchGetDataScrollByHQL("select u.id,u.account,u.pwd from UserLogin u", 0, 5000);
        List<UserLogin> list = new ArrayList(5000);
        while (scrollableResults.next()) {
            UserLogin userLogin = new UserLogin();
            userLogin.setId(scrollableResults.getInteger(0));
            userLogin.setAccount(scrollableResults.getString(1));
            userLogin.setPwd(scrollableResults.getString(2));
            list.add(userLogin);
        }
        for (UserLogin userLogin : list) {
            System.out.println("ID:" + userLogin.getId() + "用户名:" + userLogin.getAccount() + "密码:" + userLogin.getPwd());
        }
        System.out.println("###################################################################################");
    }

    @Test
    @Transactional
    public void testScrollSQL() {
        ScrollableResults scrollableResult = supperBaseDAO.batchGetDataScrollBySQL("select u.id,u.account,u.pwd from user_login u", 0, 5000);
        List<UserLogin> lis = new ArrayList(5000);
        System.out.println(scrollableResult.getRowNumber());
        while (scrollableResult.next()) {
            UserLogin userLogin = new UserLogin();
            userLogin.setId((Integer)scrollableResult.get(0));
            userLogin.setAccount((String)scrollableResult.get(1));
            userLogin.setPwd((String)scrollableResult.get(2));
            lis.add(userLogin);
        }
        for (UserLogin userLogin : lis) {
            System.out.println("ID:" + userLogin.getId() + "用户名:" + userLogin.getAccount() + "密码:" + userLogin.getPwd());
        }
    }
    @Test
    @Transactional
    public void testSQLEntity(){
        List<List> clazzs=new ArrayList();
        List cla=new ArrayList();
        cla.add("ca");
        cla.add(ArticleCategory.class);
        clazzs.add(cla);
        List clb=new ArrayList();
        clb.add("ar");
        clb.add("ca.articleContents");
        clazzs.add(clb);
        List lis=supperBaseDAO.findBySqlWithJoin("select {ar.*},{ca.*} from article_category ca,article_content ar where ar.category=ca.id",clazzs,0,0);
        for (Object obj : lis) {
            Object[] obs=(Object[])obj;
            for(Object ob:obs){
            if(ob instanceof UserLogin){
                UserLogin userLogin=(UserLogin)ob;
                System.out.println("ID:" + userLogin.getId() + "用户名:" + userLogin.getAccount() + "密码:" + userLogin.getPwd()+"关联对象:"+userLogin.getUserInfo().getUsername());
             }
            if(ob instanceof UserInfo){
                System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            }
            }
        }
    }
    @Test
    @Transactional
    public void testJoin(){
    List list=supperBaseDAO.sessionFactory.getCurrentSession().createSQLQuery("select user.* from user_login login,user_info user where user.loginid=login.id").addEntity("user", UserInfo.class).list();
    System.out.println(((UserInfo) list.get(0)).getUserLogin().getAccount());
    }

    @Test
    @Transactional
    public void testMoreBean(){
        List<List> clazzs=new ArrayList();
        List cla=new ArrayList();
        cla.add("ca");
        cla.add(ArticleCategory.class);

        List clb=new ArrayList();
        clb.add("ar");
        clb.add(ArticleContent.class);

        clazzs.add(clb);
        clazzs.add(cla);
        List lis=supperBaseDAO.findMoreBeanBySql("select {ar.*},{ca.*} from article_category ca,article_content ar where ar.id=ca.id", clazzs, 0, 0);
        lis.toString();
        System.out.print("!!!!");
    }

    @Test
    @Transactional
    public void testExcuteSQL(){
        supperBaseDAO.excudeSQL("insert into user_login(account,pwd) values('acc','123456')");
    }

    //测试使用SQL查询DTO
    @Test
    @Transactional
    public void testGetDTO(){
        List<ArticleModel> l=supperBaseDAO.getListBySQL("select a.id,a.title,a.content,a.visitcount,c.category from article_content a,article_category c where a.category=c.id",ArticleModel.class,0,3);
        System.out.println("!!!!");
        for(ArticleModel articleModel:l){
            System.out.println(articleModel.getCategory());
        }
    }
}


补充:Hibernate的Criteria没有实现,需要按需实现,由于抽象类中的方法也是泛型方法,所有有的方法是可以直接跨泛型限制的,例如UserInfoDAOImp泛型指定是UserInfo,但使用泛型方法时可以传入泛型Article,从而查询Article的数据。
至于HQL语句,更多可以参考Hibernate官方文档。

猜你喜欢

转载自dr-yanglong.iteye.com/blog/2009075