Hibernate

一。简述

    1.优点:

        Hibernate的好处:拥有通用的数据库操作方法,除特殊查询外不用手动去写SQL

    2.通用DAO的封装,由于通用性考虑所以所有返回值在使用前需强转成所要查询的类型

package com.hibernate.dao;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import com.inventec.ps.util.CheckUtils;

/**
 * The Class BasicHibernateDAO.
 * 
 * @author yongqi_wang
 */

public abstract class AbstractHibernateDAO {

	public final Logger logger = LoggerFactory.getLogger(this.getClass());

	/** The session factory. */
	protected SessionFactory sessionFactory;

	/**
	 * Gets the session factory.
	 * 
	 * @return the session factory
	 */
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * Sets the session factory.
	 * 
	 * @param sessionFactory
	 *            the session factory
	 */
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/**
	 * Open session. 打开后必须主动关闭。
	 * 
	 * @return the session
	 */
	protected Session openSession() {
		return sessionFactory.openSession();
	}

	/**
	 * Current session. DAO 必须在事务(比如@Transactional)的管理内,否则得不到session。
	 * 创建的session会和绑定到当前线程,而openSession不会。
	 * 创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭。
	 * 
	 * @return the session
	 */
	protected Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	

	/**
	 * id查询
	 * @param clazz  类型.class(不得为空)
	 * @param id     主键id
	 */
	@Transactional(readOnly = false)
	public Object selectObjectById(Class<?> clazz,String id){
		return currentSession().get(clazz, id);
	}
	/**
	 * 添加
	 */
	@Transactional(readOnly = false)
	public void save(Object object){
		currentSession().save(object);
	}
	/**
	 * 批量添加
	 */
	@Transactional(readOnly = false)
	public void saveAll(List<?> list){
		Session session = currentSession();
		for (int i = 0;i < list.size();i++) {
			if(i % 500 == 0){
				session.flush();
			}
			session.save(list.get(i));
		}
		session.flush();
		session.clear();
	}
	
	/**
	 * 修改
	 */
	@Transactional(readOnly = false)
	public void update(Object object){
		currentSession().update(object);
	}
	/**
	 * 删除
	 */
	@Transactional(readOnly = false)
	public void delete(Object object){
		currentSession().delete(object);
	}
	/**
	 * 根据id删除 
	 * @param clazz 实体类class (不得为空)
	 * @param id 要删除的对象id
	 */
	@Transactional(readOnly = false)
	public void deleteObjectById(Class<?> clazz, String id) {
		Session session = currentSession();
		Object record = session.get(clazz, id);
		if(CheckUtils.noEmpty(record)){session.delete(record);}
	}
	/**
	 * 批量删除
	 */
	@Transactional(readOnly = false)
	public void deleteAll(List<?> list){
		Session session = currentSession();
		for (int i = 0;i < list.size();i++) {
			if(i % 500 == 0){
				session.flush();
			}
			session.delete(list.get(i));
		}
		session.flush();
		session.clear();
	}
	/**
	 * 根据多个id查询
	 * @param clazz 对象class
	 * @param list id的List集合
	 * @return
	 */
	@Transactional(readOnly = false)
	public List<?> selectListById(Class<?> clazz,List<String> list){
		Session session = currentSession();
		Criteria crit = session.createCriteria(clazz);
		if(list != null && list.size() > 0){
			crit.add(Restrictions.in("id", list));
		}
		List<?> li = crit.list();
		session.flush();
		session.clear();
		return li; 
	}
	/**
	 * 条件查询    排序条件写的比较烂,也懒的改了  有需要的朋友可以自己修改下
	 * @param clazz 要查询的实体类class (不得为空)
	 * @param map 查询条件  key:属性名  value:要查询的值
	 * @param map2 分页与排序条件 
	 */
	@Transactional(readOnly = false)
	public List<?> selectListByMap(Class<?> clazz,Map<String,Object> map,Map<String,Object> map2){
		Session session = currentSession();
		Criteria crit = session.createCriteria(clazz);
		if(CheckUtils.noEmpty(map)){
			crit = crit.add(Restrictions.allEq(map));
		}
		if (CheckUtils.noEmpty(map2.get("order"))?map2.get("order").equals("desc"):false) {
			if(CheckUtils.noEmpty(map2.get("sort"))){
				crit.addOrder(Order.desc(map2.get("sort").toString()));
			}
		} else {
			if(CheckUtils.noEmpty(map2.get("sort"))){
				crit.addOrder(Order.asc(map2.get("sort").toString()));
			}
		}
		if(CheckUtils.noEmpty(map2.get("page")) && CheckUtils.noEmpty(map2.get("rows"))){
			Integer rows = (Integer) (map2.get("rows"));
			Integer page = (Integer) (map2.get("page"));
			crit.setFirstResult(rows * (page - 1));
			crit.setMaxResults(rows);
		}
		List<?> list = crit.list();
		session.flush();
		session.clear();
		return list;
	}
	/**
	 * 条件查询数据条数
	 * @param clazz 要查询的实体类class (不得为空)
	 * @param map 查询条件
	 */
	@Transactional(readOnly = false)
	public Integer selectListByMapNumber(Class<?> clazz,Map<String,Object> map){
		Session session = currentSession();
		Criteria crit = session.createCriteria(clazz);
		if(CheckUtils.noEmpty(map)){
			crit = crit.add(Restrictions.allEq(map));
		}
		return ((Number) crit.setProjection(Projections.rowCount()).uniqueResult()).intValue();
	}
}

3.hibernate自定义sql

    此方法不建议经常使用,因为这样会造成大量的sql语法写入service中,与MVC的理念偏离,如有必要建议在dao中使用StringBuffer将所有sql进行书写,虽然会造成代码冗余但会使代码可读性提高

    /**
     * 测试用例
     * 注意:
     *	① 根据hibernate hql语句的生成特性,会将所有的查询条件封装成map
     *		所以如果使用map来作为方法的参数来达到通用性的目的,提交返回值前
     *		要将此map关闭,否则map会在hql语句生成时被一起传递到hql语句中
     *		导致查询失败抛出异常
     *	② 查询后要清空session缓存,防止脏数据产生
     *	③ 自定义sql书写时需注意sql语法,建议先使用Navict或其他工具验证sql后再书写
     *	④ sql中有字符串作为判断条件时使用单引号将参数括起,具体书写与sql语法一致在使用时注意标点符号
     * @param clazz 要查询的对象class
     * @param map 由于自定义sql无法达成与实体类映射关系,所以需要手动做ORM
     *            1.要查询的数据库中的 字段名 as 实体类名
     *	          2.要查询的数据库表名
     *	  
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<?> queryUaMaterialhistoryByMap(Class<?> clazz,Map<String, Object> map) {
        Session session = currentSession();
        StringBuffer sb = new StringBuffer();
        sb.append("select ");
        sb.append(map.get("select"));
        sb.append(" from ");
        sb.append(map.get("from"));
		if(CheckUtils.noEmpty(map.get("where")){
			sb.append(" where ");
			sb.append(map.get("where"));
		}
        if (CheckUtils.noEmpty(map.get("order")) ? map.get("order").equals("desc") : false) {
            sb.append(" order by ");
            sb.append(map.get("sort"));
            sb.append(" desc ");
        } else {
            sb.append(" order by ");
            sb.append(map.get("sort"));
            sb.append(" asc ");
        }
        Query query = session.createSQLQuery(sb.toString());
        if (CheckUtils.noEmpty(map.get("page")) && CheckUtils.noEmpty(map.get("rows"))) {
            Integer rows = (Integer) (map.get("rows"));
            Integer page = (Integer) (map.get("page"));
            query.setFirstResult(rows * (page - 1));
            query.setMaxResults(rows);
        }
        map.clear();
        List<?> list = query.setResultTransformer(Transformers.aliasToBean(clazz)).list();
        session.flush();
        session.clear();
        return list;
    }
4.session中createSQLQuery和createQuery方法的区别

    ① createQuery 所有查询条件使用实体类中的属性名

    ② createSQLQuery 放弃hibernate的关系映射操作,自己手动通过字段别名映射实体

    ③ 使用createQuery可以不写select语句直接从from语句开始书写

        例:

Query query = session.createQuery("from TestUser");
List<User> list = query.list();

5.openSession与currentSession的区别
    ① 功能:
openSession每一次调用都会产生一个新的session
currentSession 一个线程获得的session是同一个
    ② 使用:
      (1)currentSession必须在hibernate.cfg.xml中进行额外的配置
      (2)currentSession获得的Session对象必须运行在事务中
      (3)currentSession所获得的Session对象在事务结束后会自动关闭
      (4)currentSession进行Session的线程绑定,可以进行事务控制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值