在Hibernate中的一个对tree树节点查询封装的通用工具类

1.前言 

        树的操作很多都是通用的,但是通用的特点虽然不多,但是操作的时候却并不简单.所以笔者简单谢了一个操作类,由于时间原因,里面方法并没有全部验证,需要的童鞋可以拿过去改改用,大体上每有太多问题;

2.主要功能

   实现父节点查询,子节点查询,可附加搜索深度/节点类型/是否包含节点自身等查询条件的查询;

3.具体实现

 

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;

/**
 * 
 * @author dview76
 * 通过HQL语句操作tree的工具类,此类中的方法不会管理相关事务,
 * 操作的时候,如果父节点是一个对象,可用parent.id的形式出入hql语句;
 */
public class TreeHelper<T>{
	/**
	 * 排序方式,升序还是降序
	 * @author dview76
	 *
	 */
	public enum OrderType{
		DESC("desc"),ASC("asc");
		private String typeString;		
		private OrderType(String type){
			this.typeString=type;
		}
		public String getTypeValue(){
			return this.typeString;
		}
	}
	/**
	 * 节点的类型1表示父节点,2表示子节点,3表示所有节点,默认为3
	 * @author dview76
	 *
	 */
	public enum NodeType{
		Parent(1),Leaf(2),All(3);
		private Integer type=3;		
		private NodeType(Integer type){
			this.type=type;
		}
		public Integer getTypeValue(){
			return this.type;
		}
	}
	/**
	 * 
	 * @author dview76
	 * 根据传入的entity,返回一个树形结构
	 * @param <T>
	 */
	public interface HibernateTreeI<E>{
		public Object getId(E t);
		public Object getPid(E t);		
	}
	
	    private String tableNameString=null;
		private String pidName;
		private String idName;
		//private Class<T> cls;
		private HibernateTreeI<T> tree;
		public TreeHelper(HibernateTreeI<T> tree,String tableName,String pidName,String idName) {
               this.tableNameString=tableName;
               this.pidName=pidName;
               this.idName=idName;
               this.tree=tree;
		}
		/**
		 * 需要注意的是,这里使用的hql语句
		 * @param session hibernate的session
		 * @param order 拍下方式,升序/降序
		 * @param sortColumns 排序使用的字段名称
		 * @return 指定父节点下面的,下一级的子节点列表;
		 */
		public List<T> getSubTreeByPid(Session session,Object pidValue,OrderType orderType,String...sortColumns) {
			String hql = null;
			if(pidValue==null)
			{
				hql="select table_ from "+tableNameString+" table_ where table_."+pidName+" is null";
			} else{
				hql="select table_ from "+tableNameString+" table_ where table_."+pidName+"=:pv";
			}
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("pv", pidValue);
			hql+=getOrderSortHqlString(orderType, sortColumns);			
			return (List<T>) this.findList(session, hql, params);			
		}
		
		public T getNodeById(Session session,Object idValue,OrderType orderType,String hqlSelectString,String...sortColumns) {
			String hql = null;
			if(idValue==null)
			{
				hql="select table_ from "+tableNameString+" table_ where table_."+idName+" is null";
			} else{
				hql="select table_ from "+tableNameString+" table_ where table_."+idName+"=:id";
			}
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("id", idValue);
			if(hqlSelectString!=null){
				hql+=hqlSelectString;
			}
			hql+=getOrderSortHqlString(orderType, sortColumns);			
			return findOne(session, hql, params);	
		}
		/**
		 * 得到指定节点的子节点集合
		 * @param session
		 * @param pids a,b,c这种以逗号分隔的值
		 * @param orderType
		 * @param sortColumns
		 * @return
		 */
		public List<T> getSubNodeByPids(Session session,List<Object> pids,OrderType orderType,String hqlSelectString,String...sortColumns) {
			if(pids==null||pids.isEmpty())
				return new ArrayList<T>();
			String hql = null;
				hql="select table_ from "+tableNameString+" table_ where table_."+pidName+" in (:pvs)";		
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("pvs",pids);
			if(hqlSelectString!=null)
				hql+=hqlSelectString;
			hql+=getOrderSortHqlString(orderType, sortColumns);	
			List<T> list=(List<T>) this.findList(session, hql, params);	
			if(list==null){
				list=new ArrayList<T>();
			}				
			return 		list;
		}
		/**
		 * 得到指定节点的子节点的父节点的列表,可以理解为是对传入的有子节点的指定节点的过滤保留
		 * @param session
		 * @param pids
		 * @param orderType
		 * @param sortColumns
		 * @return
		 */
		public List<Object> getSubPidsByPids(Session session,List<Object> pids,OrderType orderType,String hqlSelectString,String...sortColumns) {
			if(pids==null||pids.isEmpty())
				return new ArrayList<Object>();
			String hql = null;
				hql="select distinct table_."+pidName+" from "+tableNameString+" table_ where table_."+pidName+" in (:pv)";		
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("pv",pids);
			if(hqlSelectString!=null)
				hql+=hqlSelectString;
			hql+=getOrderSortHqlString(orderType, sortColumns);	
			List<Object> objs=(List<Object>) this.findList(session, hql, params);			
		    if(objs==null)
		    {
		    	objs=new ArrayList<Object>();
		    }
			return objs;
		} 
		/**
		 * 得到指定节点的子节点的子节点的列表
		 * @param session
		 * @param pids
		 * @param orderType
		 * @param sortColumns
		 * @return
		 */
		public List<Object> getSubIdsByPids(Session session,List<Object> pids,OrderType orderType,String hqlSelectString,String...sortColumns) {
			if(pids==null||pids.isEmpty())
				return new ArrayList<Object>();
			String hql = null;
				hql="select distinct table_."+idName+" from "+tableNameString+" table_ where table_."+pidName+" in (:pv)";		
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("pv",pids);
			if(hqlSelectString!=null)
				hql+=hqlSelectString;
			hql+=getOrderSortHqlString(orderType, sortColumns);	
			List<Object> objs=(List<Object>) this.findList(session, hql, params);			
		    if(objs==null)
		    {
		    	objs=new ArrayList<Object>();
		    }
			return objs;
		} 
		
		
		/**
		 * 
		 * @param session
		 * @param pidValue
		 * @param orderType
		 * @param hqlSelectString 自定义搜索条件,实体使用table_替代,如" and table_.status=1";
		 * @param sortColumns
		 * @return
		 */
		public List<T> getSubTreeByPid(Session session,Object pidValue,OrderType orderType,String hqlSelectString,String...sortColumns) {
			String hql = null;
			if(pidValue==null)
			{
				hql="select table_ from "+tableNameString+" table_ where table_."+pidName+" is null";
			} else{
				hql="select table_ from "+tableNameString+" table_ where table_."+pidName+"=:pv";
			}
			if(hqlSelectString!=null)
			hql+=hqlSelectString;
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("pv", pidValue);
			hql+=getOrderSortHqlString(orderType, sortColumns);			
			return (List<T>) this.findList(session, hql, params);			
		}
		
		/**
		 * 得到所有的父节点;
		 * @param hqlSelectString 自定义搜索条件,实体使用table_替代,如 " and table_.status=1";
		 * @return
		 */
		public List<Object> getAllPids(Session session,String hqlSelectString){
			String hqlString="select distinct table_."+pidName+" from "+tableNameString+" table_ where 1=1";
			if(hqlSelectString!=null)
				hqlString+=hqlSelectString;
			List<Object> list=(List<Object>) this.findList(session, hqlString,null);
			return list;
		}
		/**
		 * 得到排序的hql片段语句
		 * @param orderType
		 * @param sortColumns
		 * @param params 向此params中增加排序的相关参数
		 * @return
		 */
		private String getOrderSortHqlString(OrderType orderType,String...sortColumns){
			String hql="";
			String orderContentString="";
			if(sortColumns==null)
				sortColumns=new String[]{idName};
			if(sortColumns!=null){
				hql=" order by";
				for(int i=0;i<sortColumns.length;i++){
					String s=sortColumns[i];
					if(i>0){
						hql+=",";
					}
					hql+=" table_."+s;
					
				}
			}
			if(orderType!=null)
			hql+=" "+orderType.getTypeValue();
			return hql;
		}
	
	/**
	 * 根据父id,得到子节点的数量
	 * @param id
	 * @return
	 */
	public Long getCountOfSubNodeByPid(Session session,Object pidValue,String hqlSelectString){
		String hql = null;
		if(pidValue==null)
		{
			hql="select count(*) from "+tableNameString+" table_ where table_."+pidName+" is null";
		} else{
			hql="select count(*) from "+tableNameString+" table_ where table_."+pidName+"=:pv";
		}
		if(hqlSelectString!=null)
			hql+=hqlSelectString;
		Map<String,Object> params=new HashMap<String,Object>();
		params.put("pv", pidValue);
		return this.count(session, hql,params);
	}
	
	
	/**
	 * 得到指定父节点下面的,所有节点,可以指定搜索的深度,搜索为null或者达到指定深度会自动返回数据
	 * @param session
	 * @param pidValue
	 * @param deep 搜索的深度,默认为1,最小为1;
	 * @param isContenSelf 是否包含自身
	 * @return 如果没有,返回一个长度为0的list,无序状态
	 */
	public List<T> getAllNodesByPid(Session session,Object pidValue,int deep,boolean isContenSelf,NodeType nodeType,String hqlSelectString){
		List<T> list=new ArrayList<T>();
		List<T> listResult=new ArrayList<T>();
		/**
		 * 用来保存搜索结果中的所有的父节点;
		 */
		List<Object> parentIdsList=null;	
		/**
		 * 传入搜索的父节点
		 */
		List<Object> pidsList=new ArrayList<Object>();
		pidsList.add(pidValue);
		parentIdsList=this.searchAllNodesByPid(session,pidsList, deep,isContenSelf,nodeType,list,hqlSelectString);
		if(!nodeType.equals(NodeType.All))
		{
			//开始过滤节点
			for(T t:list){
		    	try {
		    		//Field field=cls.getDeclaredField(pidName);
		    		//field.setAccessible(true);
		    		Object parentObject;//=field.get(t);	
		    		parentObject=tree.getPid(t);
		            parentIdsList.add(parentObject);	    		
				} catch (Exception e) {
					continue;
				}	    	    	    	
		    }
			for(T t:list){
				try{
					//Field field=cls.getDeclaredField(idName);
		           // field.setAccessible(true);
		            Object idObject;//field.get(t);
		            idObject=tree.getId(t);
		            if(nodeType.equals(NodeType.Leaf)&&!parentIdsList.contains(t))
					{
		            	listResult.add(t);
		            }else if(nodeType.equals(NodeType.Parent)&&parentIdsList.contains(t)){
		            	listResult.add(t);
		            }           
				}catch(Exception e){
					continue;
				}
			}
		}else{
			listResult.addAll(list);
		}	
		if(isContenSelf)
		{
			if(nodeType.equals(NodeType.All))
			{
				
				T t=this.getNodeById(session,pidValue,OrderType.ASC,hqlSelectString,null);
				listResult.add(t);
			}else{
			     Long count=getCountOfSubNodeByPid(session, pidValue, hqlSelectString);
			     if((nodeType.equals(NodeType.Leaf)&&count<1)||(nodeType.equals(NodeType.Parent)&&count>0)){
			    	 T t=this.getNodeById(session,pidValue,OrderType.ASC,hqlSelectString,null);
			    	 listResult.add(t);
			     }
			}
		}
		return listResult;
	}
	/**
	 * 返回指定节点搜索深度的下一层节点
	 * @param session
	 * @param pidValue
	 * @param deep
	 * @param isContenSelf
	 * @param nodeType
	 * @param list
	 * @param hqlSelectString
	 * @param parentIds
	 * @return 返回指定节点搜索深度的下一层节点的父节点列表,当NodeType为all的时候返回空列表
	 */
	private List<Object> searchAllNodesByPid(Session session,List<Object> pidValues,int deep,boolean isContenSelf, NodeType nodeType,List<T> list,String hqlSelectString){
		String hql = "";
		if(deep<1)
		{
			if(nodeType.equals(NodeType.All))
			return new ArrayList<Object>();	
			List<Object> pList=(List<Object>)this.getSubIdsByPids(session, pidValues,OrderType.ASC,hqlSelectString,null);
				return pList;
		}
		List<T> tempList=this.getSubNodeByPids(session, pidValues, OrderType.ASC, hqlSelectString, null);
		if(tempList==null||tempList.isEmpty())
	    {
	    	return new ArrayList<Object>();
	    }
	   List<Object> pids=new ArrayList<Object>();
	   list.addAll(tempList);
		for(T t:tempList){
	    	try {
	    		//Field field=cls.getDeclaredField(idName);
	    		//field.setAccessible(true);
	    		Object parentObject;//=field.get(t);	    	
	    		parentObject=tree.getPid(t);
	            pids.add(parentObject);	    				
			} catch (Exception e) {
				continue;
			}	    	    	    	
	    }
		return this.searchAllNodesByPid(session, pids, deep-1, isContenSelf, nodeType,list, hqlSelectString);
	}
    
    

	/**
	 * 
	 * @param session
	 * @param pidValue
	 * @param nodeType
	 * @param isIncludeSelf
	 * @param deep
	 * @param hqlSelectString
	 * @return
	 */
	public String getIdsByPid(Session session,Object pidValue,NodeType nodeType,boolean isIncludeSelf,int deep,String hqlSelectString){
		StringBuffer buffer=new StringBuffer();
		List<Object> list=this.getIdListByPid(session, pidValue,nodeType,isIncludeSelf, deep,hqlSelectString);
		for(int i=0;i<list.size();i++){
			if(i>0)
				buffer.append(",");
			buffer.append(list.get(i).toString());
		}
		return buffer.toString();
	}
	
	/**
	 * 得到指定父节点下面的子节点编号
	 * 通过先将所有父节点取出来,然后筛选,可以减少查询次数;
	 * @param session
	 * @param pidValue
	 * @param deep 指定搜索的深度
	 * @param isOnlyLeaf
	 * @return 
	 */
	public List<Object> getIdListByPid(Session session,Object pidValue,NodeType nodeType,boolean isIncludeSelf,int deep,String hqlSelectString){
		//保存所有子节点
		List<Object> list=new ArrayList<Object>();
		List<Object> listResult=new ArrayList<Object>();
		/**
		 * 用来保存搜索结果中的所有的父节点;
		 */
		List<Object> parentIdsList=null;	
		/**
		 * 传入搜索的父节点
		 */
		List<Object> pidsList=new ArrayList<Object>();
		pidsList.add(pidValue);
		parentIdsList=this.searchChildrenIdsByPid(session,pidsList,deep,nodeType,list,hqlSelectString);
		List<Object> parentListTempList;
		if(!nodeType.equals(NodeType.All))
		{//开始过滤节点
			parentListTempList=this.getSubPidsByPids(session, list, OrderType.ASC, hqlSelectString,null);
			parentIdsList.addAll(parentListTempList);//得到所有的父节点;
			for(Object t:list){
				try{
					if(nodeType.equals(NodeType.Leaf)&&!parentIdsList.contains(t))
					{
		            	listResult.add(t);
		            }else if(nodeType.equals(NodeType.Parent)&&parentIdsList.contains(t)){
		            	listResult.add(t);
		            }
				}catch(Exception e){
					continue;
				}
			}
			 if(nodeType.equals(NodeType.Leaf)&&list.isEmpty())
    		 {
	    	  	listResult.add(pidValue);
    		 }else if(nodeType.equals(NodeType.Parent)&&!list.isEmpty()){
	    	 listResult.add(pidValue);
    		 }
		}else{
			listResult.addAll(list);
			if(isIncludeSelf)
			{
				listResult.add(pidValue);
			}
		}	
		return listResult;
	}
	
	/**
	 * 
	 * @param session
	 * @param pidValues
	 * @param deep
	 * @param nodeType 仅仅影响返回值,NodeType.All的之后返回空的列表,其他时候返回器子节点编号列表;
	 * @param list
	 * @param hqlSelectString
	 * @return 返回的是指定节点深度的下一层节点的父节点的集合,用于判断其它节点是否是父节点,当NodeType为all的时候返回空列表;
	 */
	private List<Object> searchChildrenIdsByPid(Session session,List<Object> pidValues,int deep,NodeType nodeType,List<Object> list,String hqlSelectString){
		String hql = "";
		if(deep<1)
		{
			if(nodeType.equals(NodeType.All))
			return new ArrayList<Object>();		
			List<Object> pList=(List<Object>)this.getSubPidsByPids(session, pidValues,OrderType.ASC,hqlSelectString,null);
				return pList;
		}
		List<Object> tempList=this.getSubIdsByPids(session,pidValues,OrderType.ASC, hqlSelectString,null);
		if(tempList.isEmpty())
		{
			return tempList;
		}else{
			list.addAll(tempList);
			return this.searchChildrenIdsByPid(session,tempList, deep-1, nodeType,list, hqlSelectString);
		}
		
	}
	
    /**
     * 根据主键名称和值,取得指定节点的上级节点;
     * @param session
     * @param idName
     * @param idValue
     * @param parentName
     * @return 
     */
	public T getParent(Session session,Object idValue) {
	String hqlString=null;	
	Map<String,Object> params=new HashMap<String,Object>();
		hqlString="select p from "+tableNameString+" p,"+tableNameString+" s where s."+pidName+"=p."+idName+" and s."+idName;
	if(idValue==null){
		hqlString+="is null";	
	}else{
		hqlString+="=:idValue";
		params.put("idValue",idValue);
	}
    return this.findOne(session, hqlString, params);
	}

	/**
	 * 得到指定节点的兄弟节点,
	 * @param session
	 * @param idValue
	 * @param orderType
	 * @param isIncludeSelf 是否包含自己
	 * @param sortColumns
	 * @return
	 */
	public List<T> getTreeBrothersNode(Session session,Object idValue,boolean isIncludeSelf,OrderType orderType,String...sortColumns) {
		List<T> list=null;
		String hqlString=null;	
		Map<String,Object> params=new HashMap<String,Object>();
			hqlString="select brothers from "+tableNameString+" brothers where brothers."+idName;
		if(idValue==null){
			hqlString+="is not null";	
		}else{
			hqlString+="<>:idValue";						
		}
		if(!isIncludeSelf){
			hqlString+=" and brothers."+pidName+" in ";
			hqlString+="(select p."+pidName+" from tableNameString p,"+tableNameString+" s where s."+pidName+"=p."+idName+" and s."+idName;
		}
		if(idValue==null){
			hqlString+="is null";
		}else{
			hqlString+="=:idValue";
			params.put("idValue",idValue);
		}
		hqlString+=")";
		params.put("idValue",idValue);
		hqlString+=getOrderSortHqlString(orderType, sortColumns);
		return (List<T>) this.findList(session, hqlString, params);
	}
	
	/**
	 * List参数会自动转换,不要传入数组;
	 * @param session
	 * @param hql
	 * @param params
	 * @return
	 */
	private List<?> findList(Session session,String hql, Map<String, Object> params) {
		Query q =session.createQuery(hql);
		if (params != null && !params.isEmpty()) {
			for (String key : params.keySet()) {
				Object object=params.get(key);
				if(object instanceof List)
				{
					q.setParameterList(key,(Collection) object);
					continue;
				}
				q.setParameter(key, params.get(key));
			}
		}
		return q.list();
	}
	private Long count(Session session,String hql,Map<String, Object> params) {
		Query q = session.createQuery(hql);
		if (params != null && !params.isEmpty()) {
			for (String key : params.keySet()) {
				Object object=params.get(key);
				if(object instanceof List)
				{
					q.setParameterList(key,(Collection) object);
					continue;
				}
				q.setParameter(key, params.get(key));
			}
		}
		return (Long) q.uniqueResult();
	}
	private T findOne(Session session,String hql, Map<String, Object> params) {
		Query q =session.createQuery(hql);
		if (params != null && !params.isEmpty()) {
			for (String key : params.keySet()) {
				Object object=params.get(key);
				if(object instanceof List)
				{
					q.setParameterList(key,(Collection) object);
					continue;
				}
				q.setParameter(key, params.get(key));
			}
		}
		return (T) q.uniqueResult();
	}
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值