Hibernate4与Spring4集成

2017-04-21 20:12

1、web.xml

<filter>
        <filter-name>openSessionInViewFilter</filter-name>
           <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2、applicationContext.xml

       <!-- 阿里 druid数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <!-- 数据库基本信息配置 -->
        <property name="url" value="${ds.url}"/>
        <property name="username" value="${ds.username}"/>
        <property name="password" value="${ds.password}"/>
        <property name="driverClassName" value="${ds.driverClassName}"/>
        <!-- <property name="filters" value="${ds.filters}"/> -->
        <!-- 最大并发连接数 -->
        <property name="maxActive" value="${ds.maxActive}"/>
        <!-- 初始化连接数量 -->
        <property name="initialSize" value="${ds.initialSize}"/>
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${ds.maxWait}"/>
        <!-- 最小空闲连接数 -->
        <property name="minIdle" value="${ds.minIdle}"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${ds.timeBetweenEvictionRunsMillis}"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${ds.minEvictableIdleTimeMillis}"/>
        <property name="validationQuery" value="${ds.validationQuery}"/>
        <property name="testWhileIdle" value="${ds.testWhileIdle}"/>
        <property name="testOnBorrow" value="${ds.testOnBorrow}"/>
        <property name="testOnReturn" value="${ds.testOnReturn}"/>
<!--        <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}"/>
         打开removeAbandoned功能
        <property name="removeAbandoned" value="${removeAbandoned}"/>
        1800秒,也就是30分钟
        <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"/>
        关闭abanded连接时输出错误日志
        <property name="logAbandoned" value="${logAbandoned}"/> -->
    </bean>

    
   <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 扫描实体路径 -->  
        <property name="packagesToScan" value="net.xby1993.springmvc.**.entity" />
        <property name="hibernateProperties">
             <props>
                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                 <prop key="hibernate.show_sql">true</prop>
                 <prop key="hibernate.format_sql">true</prop>
                 <prop key="hibernate.hbm2ddl.auto">update</prop>
                 <!-- 数据库批量查询最大数 -->  
                <prop key="hibernate.jdbc.fetch_size">50</prop>  
                <!-- 数据库批量更新、添加、删除操作最大数 -->  
                <prop key="hibernate.jdbc.batch_size">50</prop>    
                <!-- 命名规则 My_NAME->MyName java驼峰变db下划线命名-->
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
             </props>
         </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" read-only="false"
                       rollback-for="java.lang.Exception"/>
            <tx:method name="remove*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>  
            <tx:method name="delete*" propagation="REQUIRED" read-only="false"
                       rollback-for="java.lang.Exception"/>
            <tx:method name="insert*" propagation="REQUIRED" read-only="false"
                       rollback-for="java.lang.Exception"/>
            <tx:method name="update*" propagation="REQUIRED" read-only="false"
                       rollback-for="java.lang.Exception"/>
            <tx:method name="save*" propagation="REQUIRED" read-only="false"
                       rollback-for="java.lang.Exception"/>
            <tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!-- 事务处理 -->
    <aop:config>
        <aop:pointcut id="pc" expression="execution(* net.xby1993..service..*(..))"/>
        <aop:advisor pointcut-ref="pc" advice-ref="txAdvice"/>
    </aop:config>
    <!--  支持@Transactional注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

3、BaseDao

package net.xby1993.common.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import net.xby1993.common.util.StringUtil;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

@SuppressWarnings("unchecked")
public class BaseDao<T> extends HibernateDaoSupport implements DAO<T>{
    // 存储泛型的实际参数
    private Class<T> clazz;

    
    public BaseDao() {
        // 谁实现该类,这就是谁的类字节码
        Class c = this.getClass();
        // 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type
        Type type = c.getGenericSuperclass();
        // 将类型强转为参数化类型
        ParameterizedType pType = (ParameterizedType) type;
        // 获取该类的父类的所有实际类型参数,也就是泛型的实际参数
        // 这里也就是获取BaseDaoImpl的实际类型参数
        Type[] actualTypeArguments = pType.getActualTypeArguments();
        // 将实际类型参数赋值给成员变量
        clazz = (Class<T>) (actualTypeArguments[0]);
    }

    @Resource(name = "sessionFactory")
    public void setMySessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    /*@Override
    public Serializable save(T entity) {
        return this.getHibernateTemplate().save(entity);
    }*/

    @Override
    public void update(T entity) {
        this.getHibernateTemplate().update(entity);
    }
    @Override
    public int bulkUpdateByHQL(String queryString,Object... values) {
        return getHibernateTemplate().bulkUpdate(queryString,values);
    }
    @Override
    public void saveOrUpdate(T entity) {
        this.getHibernateTemplate().saveOrUpdate(entity);
    }

    @Override
    public void delete(T entity) {
        this.getHibernateTemplate().delete(entity);
    }
    @Override
    public void deleteByKey(Serializable id) {
        this.delete(this.load(id));
    }
    @Override
    public void deleteAll(Collection<T> entities) {
        getHibernateTemplate().deleteAll(entities);
    }
    @Override
    public T findById(Serializable oid) {
        return (T) this.getHibernateTemplate().get(this.clazz, oid);
    }
    @Override
    public T load(Serializable id) {
        T load = (T) this.getSession().load(clazz, id);
        return load;
    }
    @Override
    public List<T> findByHQL(String queryString,Object... values){
        return (List<T>) getHibernateTemplate().find(queryString, values);
    }
    @Override
    public void executeSql(String sqlString, Object... values) {
        Query query = this.getSession().createSQLQuery(sqlString);
        if (values != null)
        {
            for (int i = 0; i < values.length; i++)
            {
                query.setParameter(i, values[i]);
            }
        }
        query.executeUpdate();
    }
    @Override
    public List<T> findBySql(String sqlString, Object... values) {
        SQLQuery query = this.getSession().createSQLQuery(sqlString);
        if (values != null)
        {
            for (int i = 0; i < values.length; i++)
            {
                query.setParameter(i, values[i]);
            }
        }
        query.addEntity(clazz);
        return query.list();
    }
    @Override
    public  T findUniqueBySql(String sqlString, Object... values) {
        SQLQuery query = this.getSession().createSQLQuery(sqlString);
        if (values != null)
        {
            for (int i = 0; i < values.length; i++)
            {
                query.setParameter(i, values[i]);
            }
        }
        query.addEntity(clazz);
        return (T) query.uniqueResult();
    }
    @Override
    public T findUniqueByHQL(String queryString, Object... values){
        Query query = this.getSession().createQuery(queryString);
        if (values != null)
        {
            for (int i = 0; i < values.length; i++)
            {
                query.setParameter(i, values[i]);
            }
        }
        return (T) query.uniqueResult();
    }
    @Override
    public List<T> findByHQL(String queryString, String[] paramNames, Object[] values){
        return (List<T>) getHibernateTemplate().findByNamedParam(queryString, paramNames, values);
    }
    @Override
    public T findUniqueByHQL(String queryString, String[] paramNames, Object[] values){
        Query query = this.getSession().createQuery(queryString);
        if (values != null)
        {
            for (int i = 0; i < values.length; i++)
            {
                query.setParameter(paramNames[i], values[i]);
            }
        }
        return (T) query.uniqueResult();
    }
    @Override
    public List<T> findByNamedQuery(String queryName, Object... values) {
        return (List<T>) getHibernateTemplate().findByNamedQuery(queryName, values);
    }
    @Override
    public List<T> findByNamedQuery(String queryName, String[] paramNames, Object[] values){
        return (List<T>) getHibernateTemplate().findByNamedQueryAndNamedParam(queryName,paramNames, values);
    }
    @Override
    public Iterator<T> iterate(String queryString,Object... values){
        return (Iterator<T>) getHibernateTemplate().iterate(queryString, values);
    }
    @Override
    public void closeIterator(Iterator it) {
        getHibernateTemplate().closeIterator(it);
    }
    @Override
    public List<T> findAll() {
        return (List<T>) this.getHibernateTemplate().find("from " + this.clazz.getSimpleName());
    }
    @Override
    public List<T> loadAll() {
        return (List<T>) getHibernateTemplate().loadAll(clazz);
    }
    
    @Override
    public Integer getRowCount(DetachedCriteria detachedCriteria) {
        // 设置记录数投影
        detachedCriteria.setProjection(Projections.rowCount());
        List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
        // 将投影置为空
        detachedCriteria.setProjection(null);
        if (list.size() > 0) {
            return list.get(0).intValue();
        }
        return null;
    }

    @Override
    public List<T> findByPage(DetachedCriteria detachedCriteria,List<Order> orders, int pageNo, int pageSize) {
        if(orders!=null){
            for(Order order:orders){
                detachedCriteria.addOrder(order);
            }
        }
        // 指定hibernate在连接查询时,只封装成一个对象
        detachedCriteria.setResultTransformer(DetachedCriteria.ROOT_ENTITY);
        pageNo=pageNo<1?1:pageNo;
        int startIndex=(pageNo-1)*pageSize;
        return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria, startIndex, pageSize);
    }
    @Override
    public Page<T> findPageForResults(DetachedCriteria criteria,List<Order> orders,
            int pageNo, int pageSize){
        if(orders!=null){
            for(Order order:orders){
                criteria.addOrder(order);
            }
        }
        pageNo=pageNo<1?1:pageNo;
        int startIndex=(pageNo-1)*pageSize;
        criteria.setProjection (Projections.rowCount());// 设置查询的结果是总数
        long totalRows = ((Number) getHibernateTemplate().findByCriteria (criteria).get(0 )).longValue();
        criteria.setProjection ( null );//设置为 null这样查询的 结果就不是总数了
      //criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        criteria.setResultTransformer (Criteria.ROOT_ENTITY ); //使用了关联类查询要设置这个,不然返回的是 object【】类型
        List<T> list=(List<T>) getHibernateTemplate().findByCriteria(criteria, startIndex, pageNo);
        Page<T> results=new Page<>();
        results.setPageNo(pageNo);
        results.setPageSize(pageSize);
        results.setPageCount(results.getTotalPages());
        results.setTotalCount(totalRows);
        results.setResults(list);
        return results;
    }
    
    @Override
    public List<T> findByCriteria(DetachedCriteria detachedCriteria) {
        return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
    }
    @Override
    public DetachedCriteria createDetachedCriteria() {
        return DetachedCriteria.forClass(clazz);
    }
    @Override
    public Criteria createCriteria() {
        return this.getSession().createCriteria(clazz);
    }
    @Override
    public List<T> findByProperty(String propertyName,Object value) {  
        String queryString = "from "+clazz.getName()+ " as model where model." + propertyName + "=?";     
        return (List<T>) getHibernateTemplate().find(queryString, value);  
    } 
    @Override
    public T findUniqueByProperty(String propertyName,Object value){
        String queryString = "select model from "+clazz.getName()+ " as model where model." + propertyName + "=?";     
        return (T) getSession().createQuery(queryString).uniqueResult(); 
    }
    @Override
    public List<T> findByExample(T entity) {  
        return getHibernateTemplate().findByExample(entity);  
    }  
    @Override
    public Object getStatValue(DetachedCriteria criteria, String propertyName,
            String StatName) {
        if (StatName.toLowerCase().equals("max"))
            criteria.setProjection(Projections.max(propertyName));
        else if (StatName.toLowerCase().equals("min"))
            criteria.setProjection(Projections.min(propertyName));
        else if (StatName.toLowerCase().equals("avg"))
            criteria.setProjection(Projections.avg(propertyName));
        else if (StatName.toLowerCase().equals("sum"))
            criteria.setProjection(Projections.sum(propertyName));
        else
            return null;
        List list = getHibernateTemplate().findByCriteria(criteria);
        criteria.setProjection(null);
        return list.get(0);
    }
    public void lock(T entity, LockMode lock) {
        getHibernateTemplate().lock(entity, lock);
    }
    @Override
    public void initialize(T proxy) {
        getHibernateTemplate().initialize(proxy);
    }
    @Override
    public void flush() {
        getHibernateTemplate().flush();
    }
    
    @Override
    public Session getSession(){
        return this.getSessionFactory().getCurrentSession();
    }

    /**
     * 取得对象的主键名.
     */
    public String getIdName() {
        ClassMetadata meta = getSessionFactory().getClassMetadata(clazz);
        return meta.getIdentifierPropertyName();
    }
    /**
     * 根据查询HQL与参数列表创建Query对象.
     * 
     * 本类封装的find()函数全部默认返回对象类型为T,当不为T时使用本函数.
     * 
     * @param values 数量可变的参数,按顺序绑定.
     */
    public Query createQuery(final String queryString, final Object... values) {
        Query query = getSession().createQuery(queryString);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i, values[i]);
            }
        }
        return query;
    }
    /**
     * 根据查询HQL与参数列表创建Query对象.
     * 
     * @param values 命名参数,按名称绑定.
     */
    public Query createQuery(final String queryString, final Map<String, ?> values) {
        Query query = getSession().createQuery(queryString);
        if (values != null) {
            query.setProperties(values);
        }
        return query;
    }
    /**
     * 按HQL分页查询.
     * 
     * @param page 分页参数.不支持其中的orderBy参数.
     * @param hql hql语句.
     * @param pageNo 当前页数.
     * @param pageSize 总页数.
     * @param values 数量可变的查询参数,按顺序绑定.
     * @return 分页查询结果, 附带结果列表及所有查询时的参数.
     */
    public Page<T> findPage(final String hql,int pageNo,int pageSize, final Object... values) {
        

        Query q = createQuery(hql, values);

        Page<T> page = new Page<T>();
        
        page.setPageNo(pageNo);
        long totalCount = countHqlResult(hql, values);
        page.setTotalCount(totalCount);
        int start = ((pageNo - 1) * pageSize);
        q.setFirstResult(start);
        q.setMaxResults(pageSize);

        List result = q.list();
        page.setResults(result);
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);
        page.setPageCount(page.getTotalPages());
        return page;
    }

    /**
     * 按HQL分页查询.
     * 
     * @param page 分页参数.
     * @param hql hql语句.
     * @param values 命名参数,按名称绑定.
     * @param pageNo 当前页数.
     * @param pageSize 总页数.
     * @return 分页查询结果, 附带结果列表及所有查询时的参数.
     */
    public Page<T> findPage(final String hql,int pageNo,int pageSize, final Map<String, ?> values) {
        Query q = createQuery(hql, values);
        Page<T> page = new Page<T>();
        
        page.setPageNo(pageNo);
        long totalCount = countHqlResult(hql, values);
        page.setTotalCount(totalCount);
        
        List result = q.list();
        page.setResults(result);
        
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);
        page.setPageCount(page.getTotalPages());
        return page;
    }
    /**
     * 执行count查询获得本次Hql查询所能获得的对象总数.
     * 
     * 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
     */
    protected long countHqlResult(final String hql, final Object... values) {
        String fromHql = hql;
        //select子句与order by子句会影响count查询,进行简单的排除.
        fromHql = "from " + StringUtil.substringAfter(fromHql, "from");
        fromHql = StringUtil.substringBefore(fromHql, "order by");

        String countHql = "select count(1) " + fromHql;

        try {
            Long count = (Long) createQuery(countHql, values).uniqueResult();
            return count;
        } catch (Exception e) {
            throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
        }
    }
    /**
     * 执行count查询获得本次Hql查询所能获得的对象总数.
     * 
     * 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
     */
    protected long countHqlResult(final String hql, final Map<String, ?> values) {
        String fromHql = hql;
        //select子句与order by子句会影响count查询,进行简单的排除.
        fromHql = "from " + StringUtil.substringAfter(fromHql, "from");
        fromHql = StringUtil.substringBefore(fromHql, "order by");

        String countHql = "select count(1) " + fromHql;

        try {
            Long count = (Long) createQuery(countHql, values).uniqueResult();
            return count;
        } catch (Exception e) {
            throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
        }
    }
    /**
     * 根据搜索条件查询前几条记录
     * @param criterions 数量可变的Criterion
     * @param orders 数量可变的Order
     * @param topCount 前几条记录
     * @param aliasNames 别名,用于多表关联查询
     * @return 列表集合
     */
    public List<T> findTopList(final List<Criterion> criterions,final String[] aliasNames,final List<Order> orders, final int topCount)
    {
        Criteria c = createCriteria(criterions,orders,aliasNames);

        c.setFirstResult(0);
        c.setMaxResults(topCount);

        List<T> result = c.list();
        return result;
    }
    /**
     * 根据Criterion条件创建Criteria.
     * 
     * 本类封装的find()函数全部默认返回对象类型为T,当不为T时使用本函数.
     * 
     * @param criterions 数量可变的Criterion.
     */
    private Criteria createCriteria(final List<Criterion> criterions,final List<Order> orders,final String[] aliasNames) {
        Criteria criteria = getSession().createCriteria(clazz);
        
        if(criterions!=null)
        {
            for (Criterion c : criterions) {
                criteria.add(c);
            }
        }
        if(aliasNames!=null)
        {
            for (String alias : aliasNames) 
            {
                String alias2 = alias;
                if(alias.indexOf(".")>0)
                {
                    int size = alias.split("\\.").length;
                    alias2 = alias.split("\\.")[size-1];
                    
                }
                
                criteria.createAlias(alias, alias2,Criteria.LEFT_JOIN);
                
            }
        }
        if(orders!=null)
        {
            for (Order order : orders) 
            {
                criteria.addOrder(order);
            }
        }
        else
        {
            criteria.addOrder(Order.desc("insertTime"));
        }
        
    
        return criteria;
    }
}

4、BaseEntity

package net.xby1993.common.dao;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UpdateTimestamp;

/**
 * 实体基类
 * @author xby taojw
 *
 */
@MappedSuperclass
public abstract  class BaseEntity implements Serializable{
    protected String id;
    protected Date insertTime;
    protected Date updateTime;
    
    @Temporal(TemporalType.TIMESTAMP)
    @Column(updatable = false)  
    @CreationTimestamp
    public Date getInsertTime() {
        return insertTime;
    }
    public void setInsertTime(Date insertTime) {
        this.insertTime = insertTime;
    }
    @UpdateTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}