树形结构可以清楚地呈现数据的从属关系,在数据库中我们可以用自关联来保存这样的关系。但是在取出数据的时候,如果采用以往的手段,免不了要进行递归操作。递归在理论上是可以解决树形结构的问题,但是如果数据量够大,目录层次够深,我们递归出层次关系是比较消耗资源的。我们可以从数据结构入手,树有它的分支,每个分支又可以延伸出新的分支,那么我们可以在每个节点中增加它的左支和右支,左支和右支良好的维护了树形体系。父节点的左支是永远小于子节点的左支,父节点的右支是永远大于子节点的右支,有了这样的关系,我们想要表现出树形结构是很简单的。所以我们将数据库表设计为自关联表,每个记录中都维护着一个坐支和右支。不必在表中添加父节点列也可以轻松搞定树状关系。
效果图:
Dao层
package cn.dk.dao;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import cn.dk.domain.Category;
import cn.dk.utils.JdbcUtils;
public class CategoryDao {
@SuppressWarnings("unchecked")
public List<Category> selectAllCategory() {
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select c.id,c.name,c.left_hand,c.right_hand,count(c.name) depth from category p,category c where p.left_hand<=c.left_hand and p.right_hand>=c.right_hand group by c.name order by c.left_hand";
try {
return (List<Category>) runner.query(sql, new BeanListHandler(
Category.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Category selectCategory(String id) {
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select id,name,left_hand,right_hand from category where id=?";
Object[] params = { id };
try {
return (Category) runner.query(sql,
new BeanHandler(Category.class), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void insertCategory(Category category) {
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "insert into category values(?,?,?,?)";
Object[] params = { category.getId(), category.getName(),
category.getLeft_hand(), category.getRight_hand() };
try {
runner.update(sql, params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public List<Category> selectParent(String id) {
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select p.id,p.name,p.left_hand,p.right_hand from category p,category c where p.left_hand <= c.left_hand and p.right_hand >= c.right_hand and c.id=? order by p.left_hand";
Object[] params = { id };
try {
return (List<Category>) runner.query(sql, new BeanListHandler(
Category.class), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void updateCategory(int left_hand) {
String sql = "update category set left_hand=left_hand+2 where left_hand>? ";
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
try {
runner.update(sql, left_hand);
} catch (SQLException e) {
throw new RuntimeException(e);
}
sql = "update category set right_hand=right_hand+2 where right_hand>=? ";
try {
runner.update(sql, left_hand);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Service 层
package cn.dk.service;
import java.util.List;
import java.util.UUID;
import cn.dk.dao.CategoryDao;
import cn.dk.domain.Category;
public class CategoryService {
public List<Category> selectAllCategory(){
CategoryDao categoryDao = new CategoryDao();
return categoryDao.selectAllCategory();
}
public List<Category> selectParents(String id){
CategoryDao categoryDao = new CategoryDao();
return categoryDao.selectParent(id);
}
public void insertCategory(String name, String parentId){
CategoryDao categoryDao = new CategoryDao();
Category parent = categoryDao.selectCategory(parentId);
Category child = new Category();
child.setId(UUID.randomUUID().toString());
child.setName(name);
child.setLeft_hand(parent.getRight_hand());
child.setRight_hand(parent.getRight_hand() + 1);
categoryDao.updateCategory(child.getLeft_hand());
categoryDao.insertCategory(child);
}
}
Web 层
package cn.dk.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.dk.service.CategoryService;
@SuppressWarnings("serial")
public class InsertCategoryServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String id = request.getParameter("id");
String name = request.getParameter("name");
CategoryService serivice = new CategoryService();
serivice.insertCategory(name, id);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package cn.dk.web;import java.io.IOException;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.dk.domain.Category;import cn.dk.service.CategoryService;@SuppressWarnings("serial")public class SelectAllCategoryServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {CategoryService service = new CategoryService();List<Category> cList = service.selectAllCategory();request.setAttribute("category", cList);request.getRequestDispatcher("/WEB-INF/pages/showList.jsp").forward(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
package cn.dk.web;import java.io.IOException;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.dk.domain.Category;import cn.dk.service.CategoryService;@SuppressWarnings("serial")public class ShowInsertServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {CategoryService service = new CategoryService();String id = request.getParameter("id");List<Category> parent = service.selectParents(id);request.setAttribute("parent", parent);request.setAttribute("id", id);request.getRequestDispatcher("/WEB-INF/pages/insert.jsp").forward(request,response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
Jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/xtree.js"></script>
<link type="text/css" href="${pageContext.request.contextPath }/css/xtree.css">
</head>
<body>
<script type="text/javascript">
<c:forEach var="ctg" items="${requestScope.category}">
<c:if test="${ctg.depth==1}">
var root = new WebFXTree('${ctg.name }');
root.setBehavior('explorer');
root.action="${pageContext.request.contextPath}/servlet/ShowInsertServlet?id=${ctg.id}";
root.target="main";
</c:if>
<c:if test="${ctg.depth==2}">
var node${ctg.depth } = new WebFXTreeItem('${ctg.name }');
node${ctg.depth}.action="${pageContext.request.contextPath}/servlet/ShowInsertServlet?id=${ctg.id}";
node${ctg.depth}.target="main";
root.add(node${ctg.depth });
</c:if>
<c:if test="${ctg.depth>2}">
var node${ctg.depth } = new WebFXTreeItem('${ctg.name }');
node${ctg.depth}.action="${pageContext.request.contextPath}/servlet/ShowInsertServlet?id=${ctg.id}";
node${ctg.depth}.target="main";
node${ctg.depth-1 }.add(node${ctg.depth });
</c:if>
</c:forEach>
document.write(root);
</script>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> </head> <body> <br><br> 您当前的位置 : <c:forEach var="p" items="${requestScope.parent}" > ${p.name }>>> </c:forEach> <form action="${pageContext.request.contextPath }/servlet/InsertCategoryServlet?id=${requestScope.id }" method="post"> <input type="text" name="name" > <input type="submit" value="增加节点"> </form> </body></html>