1. 程式人生 > >無須叠代的高性能樹結構的設計(從使用mysql數據庫儲存到使用ztree網頁輸出)

無須叠代的高性能樹結構的設計(從使用mysql數據庫儲存到使用ztree網頁輸出)

context dex list tty table round clas exception file

最後效果圖是這樣的(看起來有點醜,只是沒有美化,效果還是不錯的):

技術分享圖片

一、樹結構的數據庫儲存表設計:

  樹結構在數據庫儲存一般會使用加內關聯鍵的方式,表看起來如下:

技術分享圖片

  但是用這種表結構查詢時總是要叠代,如果運用樹結構的特點來建表,則查詢和數據處理會好得多,具體表結構看起來如下:

技術分享圖片

  數據庫建表語句為:

create table category
(
    id varchar(30) primary key,
    name varchar(30),
    lft int unique,
    rgt int unique
);

  獲取樹結構的查詢語句為:

select
child.id,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;

  得到的結果為:

技術分享圖片

  讓後將表格封裝為對象,domain與dao的代碼有:

class Category {
    private String id;
    private String name;
    private
int lft; private int rgt; private int depth;
...........

public class CategoryDao {

    private QueryRunner qr = new QueryRunner(DaoUtils.getDataSource());

    public void add(Category category) {
        try {
            //先更新,使所有let與rgt>=category.lft的都加2,為插入提供位置
            String sql = "update category set rgt=rgt+2 where rgt>=?";
            qr.update(sql, category.getLft());
            sql 
= "update category set lft=lft+2 where lft>=?"; qr.update(sql,category.getLft()); //插入 sql = "insert into category(id,name,lft,rgt) values(?,?,?,?)"; qr.update(sql, category.getId(), category.getName(), category.getLft(), category.getRgt()); } catch (SQLException e) { throw new RuntimeException(e); } } //刪除一個節點,以及其下面所有子節點 public void delete(String id) { try { Category category = find(id); String sql = "delete from category where lft>=? and rgt<=?"; qr.update(sql, category.getLft(),category.getRgt()); } catch (SQLException e) { throw new RuntimeException(e); } } public Category find(String id) { String sql = "select name,lft,rgt from category where id=?"; try { Category category = qr.query(sql, new BeanHandler<Category>(Category.class), id); category.setId(id); return category; } catch (SQLException e) { throw new RuntimeException(e); } } public List<Category> getTree(){ String sql = "select child.id,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"; try { List<Category> categories = qr.query(sql, new BeanListHandler<Category>(Category.class)); return categories; } catch (SQLException e) { throw new RuntimeException(e); } } }

  最後sevlet調用jsp輸出即可:

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Category> tree = new TreeService().getTree();
        request.setAttribute("tree",tree);
        request.getRequestDispatcher(request.getContextPath()+"/WEB-INF/jsp/tree.jsp").forward(request,response);
    }

<%@ page import="com.hao.domain.Category" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
  Created by IntelliJ IDEA.
  User: 28602
  Date: 2018/2/10
  Time: 16:32
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
    <TITLE> ZTREE DEMO </TITLE>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link rel="stylesheet" href="../css/zTreeStyle/zTreeStyle.css" type="text/css">
    <style>
        body {
            background-color: white;
            margin: 0;
            padding: 0;
            text-align: center;
        }

        div, p, table, th, td {
            list-style: none;
            margin: 0;
            padding: 0;
            color: #333;
            font-size: 12px;
            font-family: dotum, Verdana, Arial, Helvetica, AppleGothic, sans-serif;
        }

        #testIframe {
            margin-left: 10px;
        }
    </style>
    <script type="text/javascript" src="../js/jquery-1.4.4.min.js"></script>
    <script type="text/javascript" src="../js/jquery.ztree.core.js"></script>
    <SCRIPT type="text/javascript">

        var zTree;
        var demoIframe;

        var setting = {
            view: {
                dblClickExpand: false,
                showLine: true,
                selectedMulti: false
            },
            data: {
                simpleData: {
                    enable: true,
                    idKey: "id",
                    pIdKey: "pId",
                    rootPId: ""
                }
            },
            callback: {
                beforeClick: function (treeId, treeNode) {
                    var zTree = $.fn.zTree.getZTreeObj("tree");
                    if (treeNode.isParent) {
                        zTree.expandNode(treeNode);
                        return false;
                    } else {
                        demoIframe.attr("src", treeNode.file + ".html");
                        return true;
                    }
                }
            }
        };

        var zNodes = [
            <%
            //元素自上而下遍歷,list作為儲存可能插入元素的集合,其index為深度
            List<Category> list = new ArrayList<>();
            Category category = new Category();
            category.setId("0");
            list.add(0,category);
            request.setAttribute("list",list);
            %>
            <c:forEach var="ca" items="${tree}">
            <%
            Category ca =(Category) pageContext.getAttribute("ca");
            list.add(ca.getDepth(),ca);
            %>
            {id:${ca.id}, pId: ${list[ca.depth-1].id}, name: "${ca.name}", open: true},
            </c:forEach>
        ];

        $(document).ready(function () {
            var t = $("#tree");
            t = $.fn.zTree.init(t, setting, zNodes);
            demoIframe = $("#testIframe");
            demoIframe.bind("load", loadReady);
            var zTree = $.fn.zTree.getZTreeObj("tree");
            zTree.selectNode(zTree.getNodeByParam("id", 101));

        });

        function loadReady() {
            var bodyH = demoIframe.contents().find("body").get(0).scrollHeight,
                htmlH = demoIframe.contents().find("html").get(0).scrollHeight,
                maxH = Math.max(bodyH, htmlH), minH = Math.min(bodyH, htmlH),
                h = demoIframe.height() >= maxH ? minH : maxH;
            if (h < 530) h = 530;
            demoIframe.height(h);
        }

    </SCRIPT>
</HEAD>

<BODY>
<TABLE border=0 height=600px align=left>
    <TR>
        <TD width=500px align=left valign=top style="BORDER-RIGHT: #999999 ">
            <ul id="tree" class="ztree" style="width:260px; overflow:auto;"></ul>
        </TD>
    </TR>
</TABLE>

</BODY>
</HTML>

  jsp輸出使用到了ztree框架下載地址:zTree

無須叠代的高性能樹結構的設計(從使用mysql數據庫儲存到使用ztree網頁輸出)