像在淘宝、京东等网站上都会有树状分类,而要实现这种结构(web树),就要在数据库里有张表保存分类数据。
对于下图中结构的分类:

就要采用下图中的方式,比如我要找出商品下的所有分类,就只需要找出在商品左支和右支之间的所有节点就行了。

树状节点的特点:
- 每一个节点都有一个左右值。
- 如果右值-左值=1,则代表当前节点为叶子节点。
- 如果右值-左值>1,则代表当前节点有孩子节点,值在左右值之间的所有节点,即为当前结点的所有孩子节点。
数据库表设计:
数据库表设计:
create table category
(
id varchar(40) primary key,
name varchar(100),
lft int,
rgt int
);
insert into category values('1','商品',1,18);
insert into category values('2','平板电视',2,7);
insert into category values('3','冰箱',8,11);
insert into category values('4','笔记本',12,17);
insert into category values('5','长虹',3,4);
insert into category values('6','索尼',5,6);
insert into category values('7','西门子',9,10);
insert into category values('8','thinkpad',13,14);
insert into category values('9','dell',15,16);
结果如图所示:

问题:为了在页面中显示树状结构,需要得到所有结点,以及每个结点在树中的层次。
解决思路:
1、 要得到结点的层次,就是看节点有几个父亲,例如长虹有2个父亲,则它所在层次就为2。
2、 如何知道每一个节点有几个父亲呢?这个表有个特点,父亲和孩子都在同一个表中,为得到父亲所有的孩子,可以把这张表想像成两张表,一张用于保存父亲,一张表保存孩子,如下所示:
select * from category parent,category child;
3、 父亲下面的孩子有个特点,它的左值>父亲的左值,并且<父亲的右值,如下所示
select * from category parent,category child where child.lft>=parent.lft and child.rgt<=parent.rgt;
以上语句会得到父亲下面所有的孩子。
4、 对父亲所有孩子的姓名进行归组,然后使用count统计函数,这时就会知道合并了几个孩子,合并了几个孩子姓名,这个孩子就有几个父亲,从而知道它所在的层次
select child.name,count(child.name) depth from category parent,category child where child.lft>=parent.lft and child.rgt<=parent.rgt group by child.name;
5、 最后根据左值排序即可
select child.name,count(child.name) depth from category parent,category child where child.lft>=parent.lft and child.rgt<=parent.rgt group by child.name order by child.lft;
代码展示:
1. 实体类Category
package cn.itcast.domain;
/**
* Created by yvettee on 2017/10/10.
*/
public class Category {
private String id;
private String name;
private int lft;
private int rgt;
private int depth;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLft() {
return lft;
}
public void setLft(int lft) {
this.lft = lft;
}
public int getRgt() {
return rgt;
}
public void setRgt(int rgt) {
this.rgt = rgt;
}
public int getDepth() {
return depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
}
2. 具体实现类CategoryDao
package cn.itcast.dao;
import cn.itcast.domain.Category;
import cn.itcast.utils.JdbcUtils_dbcp;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.util.List;
/**
* Created by yvettee on 2017/10/10.
*/
public class CategoryDao {
public List<Category> getAll() {
try {
QueryRunner runner = new QueryRunner(JdbcUtils_dbcp.getDataSource());
String sql = "select child.id,child.name,child.lft,child.rgt,count(child.name) depth from category parent,category child where child.lft>=parent.lft and child.rgt<=parent.rgt group by(child.name) order by child.lft;";
List list = runner.query(sql, new BeanListHandler<Category>(Category.class));
return list;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3. 业务层BusinessService
package cn.itcast.service;
import cn.itcast.dao.CategoryDao;
import java.util.List;
/**
* Created by yvettee on 2017/10/10.
*/
public class BusinessService {
public List getAllCategory() {
CategoryDao dao = new CategoryDao();
return dao.getAll();
}
}
4. ListTreeServlet
,要跳转到jsp页面进行显示
package cn.itcast.web;
import cn.itcast.service.BusinessService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* Created by yvettee on 2017/10/10.
*/
@WebServlet(name = "ListTreeServlet", urlPatterns = "/listTreeServlet")
public class ListTreeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BusinessService service = new BusinessService();
List list = service.getAllCategory();
request.setAttribute("list", list);
request.getRequestDispatcher("/listTree.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
5. listTree.jsp
,在本页面要用${list}
取出数据进行一棵树的显示,没必要自己写js代码,有很多现成的控件,比如xtree,在xtree
里的index.html
中的Usage
中有示例

只需要将用到的js与css导入。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>ListTree</title>
<script src="${pageContext.request.contextPath }/js/xtree.js"></script>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/css/xtree.css">
</head>
<body>
<script type="text/javascript">
<c:forEach var="c" items="${list}">
<c:if test='${c.depth==1 }'>
var tree = new WebFXTree('${c.name}');
</c:if>
<c:if test='${c.depth==2 }'>
var node${c.depth} = new WebFXTreeItem('${c.name}'); //node2
tree.add(node${c.depth});
</c:if>
<c:if test='${c.depth>2 }'>
var node${c.depth} = new WebFXTreeItem('${c.name}'); //node3
node${c.depth-1}.add(node${c.depth}); //
</c:if>
</c:forEach>
document.write(tree);
</script>
</body>
</html>
网友评论