日期:2014-05-16  浏览次数:20455 次

基于数据库的无限级树形结构后台(非递归遍历节点,通过增加维护节点PATH字段)
/**
 * 
 * @author yangzhichao
 *
 * @param <PK>
 * @param <T>
 */
public interface TreeNode<PK extends Number, T extends TreeNode<PK, T>> extends
		Serializable {
	public static final String DEFAULT_PATH_SEPARATOR = "-";

	/**
	 * 节点标识
	 * 
	 * @return
	 */
	PK getId();

	/**
	 * 节点名字
	 * 
	 * @return
	 */
	String getName();

	/**
	 * 获取直接父节点对象
	 * 
	 * @return 直接上级对象
	 */
	T getParent();

	/**
	 * 设置父节点
	 * 
	 * @param t
	 */
	void setParent(T t);

	/**
	 * 获取路径
	 * 
	 * @return
	 */
	String getPath();

	/**
	 * 
	 * @param path
	 * @return
	 */
	void setPath(String path);

	/**
	 * 是否为叶节点
	 * 
	 * @return 返回所有叶节点
	 */
	boolean isLeaf();

	/**
	 * 判断是否为指定节点的父节点
	 * 
	 * @param child
	 *            被判断的节点
	 * @return
	 */
	boolean isParentOf(T child);

	/**
	 * 判断是否为指定节点的子节点
	 * 
	 * @param parent
	 *            被判断的节点对象
	 * @return
	 */
	boolean isChildOf(T parent);

	/**
	 * 节点是否有效
	 * 
	 * @return
	 */
	boolean isValid();

	/**
	 * 获取子节点
	 * 
	 * @return
	 */
	Collection<T> getChildren();

	/**
	 * 节点类别
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	Class getClazz();

	/**
	 * 状态
	 * 
	 * @return
	 */
	int getStatus();
}


/**
 * 树型抽象实现
 * 
 * @author yangzhichao
 * 
 */
public abstract class AbstractTreeNode<PK extends Number, T extends AbstractTreeNode<PK, T>>
		implements TreeNode<PK, T> {
	/**
	 * 标识
	 */
	private PK id;
	/**
	 * 名字
	 */
	private String name;
	/**
	 * 上级节点
	 */
	private T parent;
	/**
	 * 路径
	 */
	private String path;
	/**
	 * 直接子节点集合
	 */
	private Collection<T> children;
	/**
	 * 序号
	 */
	private int order;

	public boolean isChildOf(T parent) {
		return parent == null || this.getParent() == null ? false : this
				.getParent().equals(parent);
	}

	public boolean isParentOf(T child) {
		return child == null || child.getParent() == null ? false : this
				.equals(child.getParent());
	}

	/**
	 * 默认根据是否有子节点判断
	 */
	public boolean isLeaf() {
		return !(this.getChildren() != null && this.getChildren().size() > 0);
	}

	@SuppressWarnings("unchecked")
	public boolean equals(Object object) {
		if (!(object instanceof AbstractTreeNode)) {
			return false;
		}
		AbstractTreeNode o = (AbstractTreeNode) object;
		// 类型和ID要一致
		return new EqualsBuilder().append(this.getClazz().getName(),
				o.getClazz().getName()).append(this.getId(), o.getId())
				.isEquals();
	}

	public PK getId() {
		return id;
	}

	public void setId(PK id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public T getParent() {
		return parent;
	}

	public void setParent(T parent) {
		this.parent = parent;
	}

	public Collection<T> getChildren() {
		return children;
	}

	public void setChildren(Collection<T> children) {
		this.children = children;
	}

	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}
}


/**
 * 树型DAO接口
 * 
 * @author yangzhichao
 * 
 * @param <PK>
 * @param <T>
 */
public interface TreeNodeDao<PK extends Number, T extends TreeNode<PK, T>>
		extends BaseDao<PK, T> {
	/**
	 * 获取父亲节点
	 * 
	 * @param t
	 * @return
	 */
	T getParent(T t) throws DataAccessException;

	/**
	 * 获取直接子节点
	 * 
	 * @param t
	 * @return
	 * @throws DataAccessException
	 */
	Collection<T> getDirectChildren(T t) throws DataAccessException;

	/**
	 * 获取直接子枝干
	 * 
	 * @param t
	 * @return
	 */
	Collection<T> getDirectBranches(T t) throws DataAccessException;

	/**
	 * 获取直接叶子节点
	 * 
	 * @param t
	 * @return
	 */
	Collection<T> getDirectLeaves(T t) throws DataAccessException;

	/**
	 * 获取所有孩子
	 * 
	 * @param t
	 * @return