package ssh.base; import java.io.Serializable; import java.sql.SQLException; import java.util.LinkedHashMap; import java.util.List; import javax.annotation.Resource; import javax.persistence.Entity; import ssh.utils.QueryResult; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.stereotype.Component; //定义抽象类继承DAO,抽象出所有实体通用的方法,方便其他类继承就可以了,abstract定义了只能继承。 @Component //放到Spring里,让Spring管理 public abstract class DaoSupport implements DAO { //注入hibernateTemplate,使用protected,其他类继承后可以直接使用 public HibernateTemplate hibernateTemplate; public HibernateTemplate getHibernateTemplate() { return hibernateTemplate; } @Resource //注入hibernateTemplate public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } /**保存数据 * 调用方法:save(new User("shazhuzhu",20) */ public void save(Object entity) { hibernateTemplate.save(entity); } /**更新数据 * 调用方法:update(new User(1,"shazhuzhu",20); 其中1为ID */ public void update(Object entity) { hibernateTemplate.update(entity); //把游离状态的实体BENA同步到数据库 } /**删除单条记录 * 调用方法:delete(User.class,1); 其中1为ID */ public <T> void delete(Class<T> entityClass,Object entityid) { delete(entityClass, new Object[]{entityid}); //调用下面的方法 } //删除多条记录 public <T> void delete(Class<T> entityClass,Object[] entityids) { for(Object id:entityids){ T t=find(entityClass,id); ////调用下面的find方法先把实体类查找出来,然后在DEL,这样才能通过ID删除数据 if(t!=null) //先判断需要删除的数据是否存在 hibernateTemplate.delete(t); } } /**查询指定ID的记录 * 调用方法:find(User.class,1); 其中1为ID */ @SuppressWarnings("unchecked") public <T> T find(Class<T> entityClass, Object entityId) { return (T) hibernateTemplate.get(entityClass,(Serializable) entityId); } /** * 获得分页数据 * QueryResult<T> 泛型定义在类上。因为需要返回查询的数据List,和查询的总条数,所以需要自定义类型返回2个数据 * @param <T> 泛型 * @param entityClass 实体类 * @param firstIndex 开始索引 firstIndex和maxResult都为-1时代表不分页 * @param maxResult 需要获取的记录数 * @param wherejpql where条件语句 * @param queryParams 条件语句参数 * @param orderby 排序,LinkedHashMap先进先出,使用这个是因为先进去的放到第一位,order by key1 desc,key2 asc * @return * * 调用方法 * LinkedHashMap<String , String> orderby=new LinkedHashMap<String, String>(); * orderby.put("id", "asc"); * QueryResult<TestVo> qr=testDAO.getScrollData(TestVo.class, 1, 10,"o.name=? and o.title=?",new Object[]{"a","1"},orderby); * for (TestVo q : qr.getResultlist()) { * System.out.println(q.getName()); * } * System.out.println(qr.getTotalrecord()); */ @SuppressWarnings("unchecked") //不检查类型,不然会有黄色线提示错误。 public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult, String wherejpql,Object[] queryParams,LinkedHashMap<String, String> orderby) { QueryResult qr = new QueryResult<T>(); //定义保存数据类型 String entityname = getEntityName(entityClass); //获取实体类名称,方法下面定义了 String hql="select o from "+entityname+" o " + (wherejpql==null? "" :"where " + wherejpql) + buildOrderby(orderby); System.out.println(hql); qr.setResultlist(getListForPage(hql, firstindex, maxresult, queryParams)); //调用hibernateTemplate的扩张方法进行分页处理 String hql2="select count(o) from "+entityname+" o " + (wherejpql==null? "" :"where " + wherejpql); Long total=(Long) hibernateTemplate.find(hql2,queryParams).get(0); //查询总记录数 qr.setTotalrecord(total); return qr; } /** * HibernateTemplate 只支持 .setMaxResults(int) 方法。 * 因此,做 Spring+Hibernate 分页处理要使用到一个接口 org.springframework.orm.hibernate3.HibernateCallback * 来灵活操作数据库,该接口中有一个未实现的方法 Object doInHibernate (Session session),用以获得并利用 session 进行操作(自动创建、销毁)。 * 分页通用方法 * @param sql HQL查询语句 * @param firstindex 起始记录下标 * @param maxresult 读取记录数 * @return List 结果集 */ @SuppressWarnings("unchecked") public List getListForPage(final String hql, final int firstindex, final int maxresult,final Object[] queryParams) { try { List list = hibernateTemplate.executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException,SQLException { Query query = session.createQuery(hql); if(firstindex!=-1 && maxresult!=-1){ //方便设置-1时不分页 query.setFirstResult(firstindex); query.setMaxResults(maxresult); } setQueryParams(query, queryParams); //调用下面方法插入where传递过来的参数 return query.list(); } }); return list; } catch (RuntimeException re) { throw re; } } public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult,LinkedHashMap<String, String> orderby) { return getScrollData(entityClass,firstindex,maxresult,null,null,orderby); } public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult,String wherejpql,Object[] queryParams) { return getScrollData(entityClass,firstindex,maxresult,wherejpql,queryParams,null); } public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult) { return getScrollData(entityClass,firstindex,maxresult,null,null,null); } public <T> QueryResult<T> getScrollData(Class<T> entityClass) { return getScrollData(entityClass,-1,-1); //主方法定义-1为不分页 } /** * 获取实体类的名称 * @param <T> * @param entityClass * @return */ protected <T> String getEntityName(Class<T> entityClass) { String entityname=entityClass.getSimpleName(); //如果实体类上面的@Entity(name=xxx)没有指定名称,直接为默认类名称 Entity entity=entityClass.getAnnotation(Entity.class); //获取@Entity注解 if(entity.name()!=null&&!"".equals(entity.name())){ //判断注解的name是否为空 entityname=entity.name(); } return entityname; } /** * 组装order by语句 * @param orderby * @return // order by o.key desc,key2 asc */ protected String buildOrderby(LinkedHashMap<String, String> orderby){ StringBuffer orderbyql=new StringBuffer(""); if(orderby!=null && orderby.size()>0 ){ orderbyql.append(" order by "); for(String key:orderby.keySet()){ //取得Map的Key的集合 orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(","); } orderbyql.deleteCharAt(orderbyql.length()-1); } return orderbyql.toString(); } /** * 为Where语句传递参数 * @param query * @param queryParams * o.key = ?1 and o.name=?2 这是错误的,JPA的问号索引是从1开始的,而HibernateTemplate是从0开始的,HibernateTemplate执行HQL语句时,HQL的语句中'?'号面是不带数字的 * o.key = ? and o.name=? 正确 */ protected void setQueryParams(Query query,Object[] queryParams) { if(queryParams!=null && queryParams.length>0){ for(int i=0;i<queryParams.length;i++){ //JPA的问号索引是从1开始的,而HibernateTemplate是从0开始的 query.setParameter(i, queryParams[i]); //如果是JPA:i+1 } } } }