SSH中hibernate窍门总结
来源:互联网 发布:淘宝750海报 编辑:程序博客网 时间:2024/05/19 23:17
hibernate 就是ORM框架,就是要配置关系外键。
你不配置你用他干啥,换mybatis得了。
小系统或大项目中数据量不大的子系统能使用hibernate就用hibernate,方便简单。
这里我个人有摸索出的窍门,大家可以参考一下。
首先,逆向生成hibernate对象配置,保留多对一关系,与之对应的一对多掉,按需配置抓取方式,按需配置懒加载。
然后DAO可以使用DAO的模板类,贴出我丰富过的模版类。(使用了spring的事务管理),具体业务接口继承这个模版DAO接口,然后可以自定义一些特定的方法,然后具体业务接口的实现类继承模版DAO的实现即可。
模版接口类GenericDaoI:
package cn.zzy.tm.dao;import java.io.Serializable;import java.util.List;import org.hibernate.criterion.Criterion;import cn.zzy.tm.model.db.PageBean;/** * 增删改查通用接口 Dao层的接口可以继承本基本接口进行扩展 * * Hibernate使用小记 根据业务,常用的字段需要join的就fetch=join,不需要的就开lazy,fetch=select * * DAO泛型模板类, 提供各类基础的查询模版方法,也提供懒加载的回调接口,方便初始化懒加载的数据 * * ,(解决代码分层session关闭后懒加载失效的问题)这个偶尔使用,一般很少使用这些回调的接口, * * 因为特殊的查询全用HQL了,而HQL是可以指定特殊字段的抓取方式的。 * * * 如果某个实体内的一些字段内,只有某些少数业务查询需要fetch=join,其他大部分都不需要这部分数 * * 据的时候,建议配置文件开lazy,fetch=select 查询全用HQL指定left join fetch来抓取指定字段 * * 因为HQL查询里配置的抓取方式全无效,默认全是lazy+select,需要在代码里指定 比方说 from Teacher as t left join * fetch t.teacherAcademicTitle * * * * @author 赵泽洋 * * @param <T> * 要实现基本操作的bean的类 */public interface GenericDaoI<T extends Serializable> { /** * 回调接口,初始化代理对象用 * * @author zhaozeyang * */ public interface InitializeObjCallBack<T> { public void initializeObj(final T obj); } /** * 回调接口,初始化代理对象LIST用 * * @author zhaozeyang * */ public interface InitializeListCallBack<T> { public void initializeList(final List<T> ls); } /** * 新增一条数据 * * @param entity * 实体 */ public abstract void create(final T entity); /** * 新增一条数据 若存在则更新 * * @param entity */ public abstract void createOrUpdate(final T entity); /** * 根据主键查实体 * * @param id * 主键 * @return 查询结果 */ public abstract T findById(final Serializable id); /** * 根据主键查实体 * * @param id * @param callback * 回调接口 * @return */ public abstract T findById(final Serializable id, InitializeObjCallBack<T> callback); /** * 根据id删数据,可传多个id * * @param entityids * id序列 */ public abstract void deleteById(Serializable... entityids); /** * 更新实体类到数据库 * * @param entity * 要更新的实体类 */ public abstract void update(final T entity); /** * 查所有记录 * * @return 查询结果 */ public abstract List<T> findAll(); /** * 查所有记录 * * @param callBack * 回调接口 * @return */ public abstract List<T> findAll(InitializeListCallBack<T> callBack); /** * HQL查记录 * * @param strHQL * HQL语句 * @param params * 参数 * @return 查询结果 */ public abstract List<T> findByHQL(final String strHQL, final Object... params); /** * HQL查记录 * * @param callBack * 回调接口 * @param strHQL * HQL语句 * @param params * 参数 * @return 查询结果 */ public abstract List<T> findByHQL(InitializeListCallBack<T> callBack, final String strHQL, final Object... params); /** * HQL分页查找 * * @param strHQL * HQL语句 * @param currentPage * 查第几页 * @param pageSize * 一个页面数据的条数 * @param params * 查询结果 * @return */ public abstract PageBean<T> findByPage(final String strHQL, final int currentPage, final int pageSize, final Object... params); /** * HQL分页查找 * * @param callBack * 回调接口 * @param strHQL * @param currentPage * @param pageSize * @param params * @return */ public abstract PageBean<T> findByPage(InitializeListCallBack<T> callBack, final String strHQL, final int currentPage, final int pageSize, final Object... params); /** * 用Criteria方式查找数据 * * @param prams * @return */ public List<T> findByCriteria(Criterion... prams); /** * 用Criteria方式查找数据 * * @param callBack * 回调接口 * @param prams * @return */ public List<T> findByCriteria(InitializeListCallBack<T> callBack, Criterion... prams); public Integer getCount(); /** * 执行HQL delete update操作 */ public int executeHQL(final String strHQL, final Object... params); /** * 当返回只有一个实例的时候使用 * * @param strHQL * @param params * @return */ public Object ExecuteScalarByHql(final String strHQL, final Object... params);}
实现类GenericDaoImpl:
package cn.zzy.tm.dao.impl;import java.io.Serializable;import java.util.List;import javax.annotation.Resource;import org.hibernate.Criteria;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.criterion.Criterion;import org.hibernate.criterion.Projections;import cn.zzy.tm.dao.GenericDaoI;import cn.zzy.tm.model.db.PageBean;import cn.zzy.tm.utils.GenericsUtils;import org.springframework.stereotype.Repository;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;/** * Dao层模版类 * * @author 赵泽洋 * * @param <T> * 要实现基本操作的bean的类 * */@Transactional@Repositorypublic class GenericDaoImpl<T extends Serializable> implements GenericDaoI<T> { /** * 获取实体类类型 */ @SuppressWarnings("unchecked") protected Class<T> persistentClass = GenericsUtils .getSuperClassGenricType(this.getClass()); /** * 若反射获得泛型类类型失效,则由此方法手动设置 * * @param entityClass * 实体类类型 */ public void setEntityClass(Class<T> entityClass) { this.persistentClass = entityClass; } /** * 由spring管理的SessionFactory,注解获取 */ @Resource protected SessionFactory sessionFactory; public void create(T entity) { sessionFactory.getCurrentSession().persist(entity); } public void createOrUpdate(T entity) { sessionFactory.getCurrentSession().saveOrUpdate(entity); } @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public T findById(Serializable id) { return this.findById(id, null); } @SuppressWarnings("unchecked") @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public T findById(Serializable id, InitializeObjCallBack<T> callback) { if (id == null) throw new RuntimeException(this.persistentClass.getName() + ":传入的实体id不能为空"); Object object = sessionFactory.getCurrentSession().get( this.persistentClass, id); if (callback != null) callback.initializeObj((T) object); return (T) object; } public void deleteById(Serializable... entityids) { Session session = sessionFactory.getCurrentSession(); for (Serializable id : entityids) { session.delete(session.get(this.persistentClass, id)); } } public void update(T entity) { sessionFactory.getCurrentSession().merge(entity); } @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> findAll() { return this.findByCriteria(); } @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> findAll(InitializeListCallBack<T> callBack) { return this.findByCriteria(callBack); } @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> findByHQL(String strHQL, Object... params) { return this.findByHQL(null, strHQL, params); } @SuppressWarnings("unchecked") @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> findByHQL(InitializeListCallBack<T> callBack, String strHQL, Object... params) { Session session = sessionFactory.getCurrentSession(); Query query = session.createQuery(strHQL); for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } List<T> ls = query.list(); if (callBack != null) callBack.initializeList(ls); return ls; } @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public PageBean<T> findByPage(String strHQL, int currentPage, int pageSize, Object... params) { return this.findByPage(null, strHQL, currentPage, pageSize, params); } @SuppressWarnings("unchecked") @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public PageBean<T> findByPage(InitializeListCallBack<T> callBack, String strHQL, int currentPage, int pageSize, Object... params) { // 步骤1:创建一个PageBean对象 PageBean<T> pageBean = new PageBean<T>(); // 步骤2:获取一个数据库链接session Session session = sessionFactory.getCurrentSession(); // 步骤3:执行HQL语句完成查询动获取本页内的固定条数的数据 Query query = session.createQuery(strHQL); // 步骤4:设置查询条件-参数条件 for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } // 步骤5:设置查询条件-每页的启始记录下标 (当前也是-1)*每页个数 query.setFirstResult((currentPage - 1) * pageSize); // 步骤6:设置查询条件-控制查询记录的个数 query.setMaxResults(pageSize); // 步骤7:获取数据集合并且赋值给pageBean对象的data属性 pageBean.setData(query.list()); // 步骤8:将输入的HQL语句动态查分成符合返回记录个数的HQL语句 strHQL = "select count(*) " + strHQL.substring(strHQL.toLowerCase().indexOf("from")); //如果自定义了fetch,必须去掉fetch才能查出count(*) strHQL = strHQL.replace("fetch", ""); // 步骤9:执行HQL语句完成查询动获取本页内的固定条数的数据 query = session.createQuery(strHQL); // 步骤10:设置查询条件-参数条件 for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } // 步骤11:获取查询结果并且赋值给pageBean对象的totalRows pageBean.setTotalRows(Integer.parseInt(query.uniqueResult().toString())); // 步骤12:为剩余的pageBean属性赋值 pageBean.setCurrentPage(currentPage); pageBean.setPageSize(pageSize); if (callBack != null) callBack.initializeList(pageBean.getData()); return pageBean; } @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> findByCriteria(Criterion... prams) { return this.findByCriteria(null, prams); } @SuppressWarnings("unchecked") @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> findByCriteria(InitializeListCallBack<T> callBack, Criterion... prams) { Session session = sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(this.persistentClass); for (Criterion criterion : prams) { criteria.add(criterion); } List<T> ls = criteria.list(); if (callBack != null) callBack.initializeList(ls); return ls; } public Integer getCount() { Session session = sessionFactory.getCurrentSession(); Criteria c = session.createCriteria(this.persistentClass); c.setProjection(Projections.rowCount()); return (Integer) c.uniqueResult(); } public int executeHQL(String strHQL, Object... params) { Session session = sessionFactory.getCurrentSession(); Query query = session.createQuery(strHQL); for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } return query.executeUpdate(); } public Object ExecuteScalarByHql(String strHQL, Object... params) { Session session = sessionFactory.getCurrentSession(); Query query = session.createQuery(strHQL); for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } return query.uniqueResult(); }}
具体实现随便举个例子:
具体业务接口AdminBizI :
package cn.zzy.tm.logic;import cn.zzy.tm.dao.GenericDaoI;import cn.zzy.tm.model.db.Admin;public interface AdminBizI extends GenericDaoI<Admin> { /** * 获取能用的管理员数量,没被禁用的 * @return */ public Long getUseableAdmin();}
具体业务接口的实现类:
package cn.zzy.tm.logic.impl;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import cn.zzy.tm.dao.impl.GenericDaoImpl;import cn.zzy.tm.logic.AdminBizI;import cn.zzy.tm.model.db.Admin;@Service@Transactionalpublic class AdminBizImpl extends GenericDaoImpl<Admin> implements AdminBizI { public Long getUseableAdmin() { return (Long) this .ExecuteScalarByHql("select count(*) from Admin as t where t.adminSuspended=0"); }}
接下来是关于代码分层导致不能取得懒加载配置的数据然后hibernate session关闭的问题,解决方法有很多,但是不推荐使用spring中扩大session生命周期的方法,即OpenSessionInViewFilter,系统的性能会因为用户的网络状况受到影响,当request在生成页面完成后,session才会被释放,所以如果用户的网络状况比较差,或生成整张页面损耗服务器CPU耗时比较长时,那么连接池中的链接会迟迟不被回收,造成内存增加,系统性能受损,并发量大的时候肯定挂了。
我的解决方法就如上模板类的代码所示,回调接口,
在回调接口里把需要的数据load进来就好。
或关联查询的时候用HQL自定义抓取方式,只抓取需要的
回调接口使用举例:
studentTask = studentTaskBizImpl.findById(sessionStu.getStudentId(), new InitializeObjCallBack<StudentTask>() { public void initializeObj(StudentTask obj) { if (obj != null) { Hibernate.initialize(obj.getTask()); Hibernate.initialize(obj.getTask().getTeacher()); } } });
自定义抓取方式举例
pgb = taskBizImpl .findByPage( "from Task as t " + "left join fetch t.tmtype left join fetch t.dicByTaskWhereToDo left join fetch t.dicByTaskState left join fetch t.dicByTaskType left join fetch t.teacher " + "where t.dicByTaskState.dicId=? order by t.tmtype.tmtypeId, t.taskCreateTime ", page, rows, "200");
当然更复杂的直接用sql,可以用hibernate里的sql查询方式,自定义结果集的bean,或者spring里的JdbcTemplate。
当然涉及到项目数据量很大,肯定是不使用关系,也就不会使用hibernate,一般都把复杂业务写成存储过程,用mybatis方便sql的编写执行。
- SSH中hibernate窍门总结
- SSH中Hibernate的使用总结
- SSH视频--Hibernate总结
- Hibernate过滤器使用窍门
- Hibernate过滤器使用窍门
- SSH中Hibernate配置二级缓存
- ssh中异常总结
- strtus spring hibernate ssh面试内容总结
- hibernate中知识总结
- hibernate中关联总结
- hibernate中注解总结
- java中SSH框架总结
- SSH整合中 hibernate整合操作
- 【SSH】hibernate中Oracle数据库配置文件详解
- SSH中hibernate的事务配置
- ssh学习:hibernate中 HQL基本 查询
- ssh学习:hibernate中QBC查询
- ssh学习:hibernate中Native SQL查询
- 2015年ACM训练二分图(2):Machine Schedule
- Mysql重装
- Joomla nginx 配置
- 查看手机的进程
- Linux中如何转换用户
- SSH中hibernate窍门总结
- Ten C++11 Features Every C++ Developer Should Use
- Excel学习小记
- LeetCode 32 Longest Valid Parentheses(最长有效括号)(*)
- 12.Laravel5学习笔记:使用mongodb开发LBS应用
- JFlow 入门,新手流程设计教程
- 给UILabel局部文字添加颜色
- Mtk camera driver
- 连接MySQL失败,错误代码10038