﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-和爪哇一起走过的日子-随笔分类-hibernate</title><link>http://www.blogjava.net/lq410/category/3537.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 06:51:31 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 06:51:31 GMT</pubDate><ttl>60</ttl><item><title>不用迭代算法而快速实现的jsp树结构</title><link>http://www.blogjava.net/lq410/archive/2005/10/14/15493.html</link><dc:creator>扑扑</dc:creator><author>扑扑</author><pubDate>Fri, 14 Oct 2005 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/lq410/archive/2005/10/14/15493.html</guid><wfw:comment>http://www.blogjava.net/lq410/comments/15493.html</wfw:comment><comments>http://www.blogjava.net/lq410/archive/2005/10/14/15493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lq410/comments/commentRss/15493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lq410/services/trackbacks/15493.html</trackback:ping><description><![CDATA[<TABLE class=partsmb cellSpacing=0 border=0>
<TBODY>
<TR>
<TD></TD>
<TD><SPAN id=_ctl2_lblPermalink>
<TABLE class="fixedTable blogpost" cellSpacing=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=bvh8></TD></TR>
<TR>
<TD vAlign=top><SPAN class=bold id=LastMDatecns!1peK6gp160nydSWlLmNuMm7g!190><STRONG>7月11日</STRONG></SPAN></TD></TR>
<TR>
<TD height=4><STRONG></STRONG></TD></TR>
<TR>
<TD class=blackline><STRONG></STRONG></TD></TR>
<TR>
<TD height=4><STRONG></STRONG></TD></TR>
<TR>
<TD class=ellipse><SPAN class=bvTitle id=subjcns!1peK6gp160nydSWlLmNuMm7g!190><STRONG>不用迭代算法而快速实现的jsp树结构</STRONG></SPAN></TD></TR>
<TR>
<TD class=bvh8><STRONG></STRONG></TD></TR>
<TR>
<TD id=msgcns!1peK6gp160nydSWlLmNuMm7g!190>
<P> <BR>在web页面上实现树状结构,有点麻烦.<BR>在最近的一个MIS系统的开发中,我们项目组大量用到了树结构:比如人员的选择,单位的选择等待.<BR>这个MIS系统所用的数据库是oracle 9i.&nbsp; oracle 9i 的sql支持迭代查询.我们的树是由牛人彭越写的,不过<BR>也参照了网络上比较著名的xtree(可以到此下载:http://webfx.eae.net/),他的树算法支持无限级的树结构,不过性能好像<BR>很慢.我持保留态度.<BR>他用到的关键技术就是这句话:<BR>String sql = "select dwxh,dwbh,dwmc,dwfxh,level cc from xt_dw connect by&nbsp; prior dwxh = dwfxh start with dwfxh = 0";<BR>可是许多数据库不支持迭代查询,并且迭代查询速度真是不能忍受.有什么更好的办法呢.下面说说我的解决方案.</P>
<P>一:需求的提出<BR>1:客户需要一个关于部门人员的树结构,数据库为mysql4.1<BR>2:java实现<BR>二:建表:<BR>1:<BR>用户信息表:<BR>各字段为:用户序号,用户编号,用户名称,单位序号,密码,用户登陆号<BR>create table XT_YH<BR>(<BR>&nbsp; YHXH&nbsp; INT(9) NOT NULL auto_increment PRIMARY KEY,<BR>&nbsp; YHBH&nbsp; VARCHAR(30),<BR>&nbsp; YHMC&nbsp; VARCHAR(30),<BR>&nbsp; DWXH&nbsp; INT(9),<BR>&nbsp; PWD&nbsp;&nbsp; VARCHAR(20),<BR>&nbsp; YHDLH VARCHAR(30)<BR>)<BR>--插入三条测试数据:<BR>--insert into xt_yh(yhbh,yhmc,dwxh,pwd,yhdlh) values('licl','',2,'password','licl')<BR>--insert into xt_yh(yhbh,yhmc,dwxh,pwd,yhdlh) values('fengx','冯欣',2,'password','fengx')<BR>--insert into xt_yh(yhbh,yhmc,dwxh,pwd,yhdlh) values('wangqx','王庆香',6,'password','wangqx')<BR>2:<BR>单位部门表<BR>各字段为:单位序号,单位编号,单位名称,单位父序号<BR>create table XT_DW<BR>(<BR>&nbsp; DWXH&nbsp; int(9) NOT NULL auto_increment PRIMARY KEY,<BR>&nbsp; DWBH&nbsp; VARCHAR(10),<BR>&nbsp; DWMC&nbsp; VARCHAR(30),<BR>&nbsp; DWFXH int(9)<BR>)<BR>--插入5条测试数据<BR>--insert into xt_dw(dwbh,dwmc,dwfxh) values('0100000000','武汉科技局',0);<BR>--insert into xt_dw(dwbh,dwmc,dwfxh) values('0101000000','人事处',1);<BR>--insert into xt_dw(dwbh,dwmc,dwfxh) values('0102000000','后勤处',1);<BR>--insert into xt_dw(dwbh,dwmc,dwfxh) values('0101010000','人事处son1',2);<BR>--insert into xt_dw(dwbh,dwmc,dwfxh) values('0101020000','人事处son2',2);<BR>--insert into xt_dw(dwbh,dwmc,dwfxh) values('0102010000','后勤处son1',3);</P>
<P>注意:<BR>为了实现快速的树结构实现,我需要充分利用单位编号DWBH,DWBH才有10位编码,其中,第一第二位表示一级单位,第三第四位表示二级单位,<BR>第五六位表示三级单位...那么10位编码就可以实现五级单位的树结构.<BR>比如:测试数据的树结构如下:<BR>&nbsp; 1&nbsp; 武汉科技局:<BR>&nbsp;2&nbsp; 人事处<BR>&nbsp; 3&nbsp; 人事处son1<BR>&nbsp; 3&nbsp; 人事处son2<BR>&nbsp;2&nbsp; 后勤处<BR>&nbsp; 3后勤处son1</P>
<P>其实XT_DW表中的父序号是多余的.不过如果你要用迭代算法来实现,就是必须的<BR>才有10位编码,我只需要一句简单快速的sql语句就可以实现树结构:<BR>String sql = "select dwxh,dwbh,dwmc,dwfxh from xt_dw order by dwbh"<BR>这句sql在几乎所有的数据库平台都能执行,速度也快.<BR>下面贴出采用xtree,用10位编码而不是迭代算法实现的树:</P>
<P>/*******Constants.java**********/</P>
<P>package com.lcl.common;</P>
<P>public class Constants {<BR>&nbsp;<BR>&nbsp;public static final String DBDRIVER = "com.mysql.jdbc.Driver";&nbsp;&nbsp;&nbsp; //MYSQL驱动<BR>&nbsp;<BR>&nbsp;public static final String DBUrl="jdbc:mysql://localhost/beauoa"; //数据库url<BR>&nbsp;<BR>&nbsp;public static final String USERNAME="root";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //数据库用户名<BR>&nbsp;<BR>&nbsp;public static final String PASSWORD="root";&nbsp;&nbsp;&nbsp;&nbsp; //数据库密码<BR>&nbsp;<BR>&nbsp;<BR>}</P>
<P><BR>/**********DbAccess.java****************/</P>
<P>package com.lcl.common;</P>
<P>import java.sql.*;<BR>import java.lang.*;</P>
<P>/**<BR>&nbsp;* @author <BR>&nbsp;*<BR>&nbsp;* TODO 要更改此生成的类型注释的模板，请转至<BR>&nbsp;* 数据库访问类<BR>&nbsp;*/<BR>public class DbAccess<BR>{&nbsp; <BR>&nbsp;String strDBDriver = Constants.DBDRIVER;<BR>&nbsp;String strDBUrl = Constants.DBUrl;<BR>&nbsp;String username = Constants.USERNAME;<BR>&nbsp;String password = Constants.PASSWORD;<BR>&nbsp;private Connection conn = null;<BR>&nbsp;private Statement stmt = null;<BR>&nbsp;ResultSet rs=null;<BR>&nbsp;//注册数据库驱动程序<BR>&nbsp;public DbAccess()<BR>&nbsp;{&nbsp; <BR>&nbsp; try <BR>&nbsp; {&nbsp; <BR>&nbsp;&nbsp; Class.forName(strDBDriver);<BR>&nbsp; }<BR>&nbsp; //异常处理<BR>&nbsp; catch( java.lang.ClassNotFoundException e)<BR>&nbsp; {<BR>&nbsp;&nbsp; System.err.println("DbAccess():"+e.getMessage());<BR>&nbsp; }<BR>&nbsp;}<BR>&nbsp;//建立数据库连接及定义数据查询<BR>&nbsp;public ResultSet executeQuery(String sql)<BR>&nbsp;{<BR>&nbsp; rs=null;<BR>&nbsp; try<BR>&nbsp; {<BR>&nbsp;&nbsp; conn=DriverManager.getConnection(strDBUrl,username,password);<BR>&nbsp;&nbsp; stmt=conn.createStatement();<BR>&nbsp;&nbsp; rs=stmt.executeQuery(sql);<BR>&nbsp; }<BR>&nbsp; catch(SQLException ex)<BR>&nbsp; {<BR>&nbsp;&nbsp; System.err.println("ap.executeQuery:"+ex.getMessage());<BR>&nbsp; }<BR>&nbsp;<BR>&nbsp; return rs;<BR>&nbsp;}<BR>&nbsp;//定义数据操库作<BR>&nbsp;public void executeUpdate(String sql)<BR>&nbsp;{<BR>&nbsp; stmt=null;<BR>&nbsp; rs=null;<BR>&nbsp; try<BR>&nbsp; {<BR>&nbsp;&nbsp; conn=DriverManager.getConnection(strDBUrl,username,password);<BR>&nbsp;&nbsp; stmt=conn.createStatement();<BR>&nbsp;&nbsp; stmt.executeQuery(sql);<BR>&nbsp;&nbsp; stmt.close();<BR>&nbsp;&nbsp; conn.close();<BR>&nbsp; }<BR>&nbsp; catch(SQLException ex)<BR>&nbsp; {<BR>&nbsp;&nbsp; System.err.println("ap.executeQuery:"+ex.getMessage());<BR>&nbsp; }<BR>&nbsp;}<BR>&nbsp;//关闭数据库<BR>&nbsp;public void closeStmt()<BR>&nbsp;{<BR>&nbsp; try<BR>&nbsp; {<BR>&nbsp;&nbsp; stmt.close();<BR>&nbsp; }<BR>&nbsp; catch(SQLException e)<BR>&nbsp; {<BR>&nbsp;&nbsp; e.printStackTrace();<BR>&nbsp; }<BR>&nbsp;}<BR>&nbsp;public void closeConn()<BR>&nbsp;{<BR>&nbsp; try<BR>&nbsp; {<BR>&nbsp;&nbsp; conn.close();<BR>&nbsp; }<BR>&nbsp; catch(SQLException e)<BR>&nbsp; {<BR>&nbsp;&nbsp; e.printStackTrace();<BR>&nbsp; }<BR>&nbsp;}<BR>&nbsp;public static void main(String[] args){<BR>&nbsp; System.out.println("hello,it's test");<BR>&nbsp; DbAccess dbaccess = new DbAccess();<BR>&nbsp; String sql = "select * from xt_yh";<BR>&nbsp; ResultSet rs = dbaccess.executeQuery(sql);<BR>&nbsp; try<BR>&nbsp; {<BR>&nbsp;&nbsp; while(rs.next()){<BR>&nbsp;&nbsp;&nbsp; System.out.print(rs.getString(1)+rs.getString(2)+rs.getString(3)+rs.getString(4)+rs.getString(5)+rs.getString(6));<BR>&nbsp;&nbsp;&nbsp; System.out.println();<BR>&nbsp;&nbsp; }<BR>&nbsp; dbaccess.closeStmt();<BR>&nbsp; dbaccess.closeConn();<BR>&nbsp; } <BR>&nbsp; catch (SQLException e) <BR>&nbsp; {<BR>&nbsp;&nbsp; // TODO 自动生成 catch 块<BR>&nbsp;&nbsp; e.printStackTrace();<BR>&nbsp; }<BR>&nbsp;}<BR>&nbsp;}</P>
<P>&nbsp;/*********DepEmplConfig.jsp************/</P>
<P>&nbsp;&lt;%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*,com.lcl.common.*" errorPage="" %&gt;<BR>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<A href="http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</A>"&gt;<BR>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;title&gt;无标题文档&lt;/title&gt;<BR>&lt;HEAD&gt;<BR>&lt;script type="text/javascript" src="../resources/xDataTree.js"&gt;&lt;/script&gt;<BR>&lt;link type="text/css" rel="stylesheet" href="../resources/xtree.css" /&gt;<BR>&lt;style type="text/css"&gt;</P>
<P>body {<BR>&nbsp;background: white;<BR>&nbsp;color:&nbsp; black;<BR>}<BR>&lt;/style&gt;<BR>&lt;TITLE&gt; New Document &lt;/TITLE&gt;<BR>&lt;META NAME="Generator" CONTENT="EditPlus"&gt;<BR>&lt;META NAME="Author" CONTENT=""&gt;<BR>&lt;META NAME="Keywords" CONTENT=""&gt;<BR>&lt;META NAME="Description" CONTENT=""&gt;<BR>&lt;/HEAD&gt;<BR>&lt;script type="text/javascript"&gt;&nbsp; <BR>webFXTreeConfig.rootIcon&nbsp; = "../resources/images/xp/folder.png";<BR>webFXTreeConfig.openRootIcon = "../resources/images/xp/openfolder.png";<BR>webFXTreeConfig.folderIcon&nbsp; = "../resources/images/xp/folder.png";<BR>webFXTreeConfig.openFolderIcon = "../resources/images/xp/openfolder.png";<BR>webFXTreeConfig.fileIcon&nbsp; = "../resources/images/xp/file.png";<BR>webFXTreeConfig.lMinusIcon&nbsp; = "../resources/images/xp/Lminus.png";<BR>webFXTreeConfig.lPlusIcon&nbsp; = "../resources/images/xp/Lplus.png";<BR>webFXTreeConfig.tMinusIcon&nbsp; = "../resources/images/xp/Tminus.png";<BR>webFXTreeConfig.tPlusIcon&nbsp; = "../resources/images/xp/Tplus.png";<BR>webFXTreeConfig.iIcon&nbsp;&nbsp; = "../resources/images/xp/I.png";<BR>webFXTreeConfig.lIcon&nbsp;&nbsp; = "../resources/images/xp/L.png";<BR>webFXTreeConfig.tIcon&nbsp;&nbsp; = "../resources/images/xp/T.png";<BR>webFXTreeConfig.blankIcon&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = "../resources/images/blank.png";</P>
<P>var tree = new WebFXTree("单位人员基本情况","R0");<BR>var child;<BR>var nodeToAddPerson;</P>
<P>function addDeptTreeNode(preNodeLevel,curNodeLevel,dispLabel,sKey,sTag) {<BR>&nbsp; if(curNodeLevel==1) {<BR>&nbsp;&nbsp;&nbsp;&nbsp; child = tree.add(new WebFXTreeItem(dispLabel,sKey,sTag));<BR>&nbsp; }<BR>&nbsp; else {<BR>&nbsp;&nbsp;&nbsp; if(curNodeLevel==preNodeLevel) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(child.parentNode)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; child = child.parentNode.add(new WebFXTreeItem(dispLabel,sKey,sTag));<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; if(curNodeLevel&gt;preNodeLevel) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; child = child.add(new WebFXTreeItem(dispLabel,sKey,sTag));<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; if(curNodeLevel&lt;preNodeLevel) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i=0;i&lt;preNodeLevel-curNodeLevel+1;i++) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; child = child.parentNode;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; child = child.add(new WebFXTreeItem(dispLabel,sKey,sTag));<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp; }<BR>&nbsp; return child;<BR>}</P>
<P>function treeClick() {<BR>&nbsp;if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp; if(tree.getSelected().childNodes.length==0&amp;&amp;tree.getSelected().key!="R0") <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdDelete.disabled = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp; else <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdDelete.disabled = true; <BR>&nbsp;&nbsp;&nbsp;&nbsp; if(tree.getSelected().key.substr(0,2)=="RZ") {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdAddDept.disabled = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdAddPeople.disabled = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var strYhxh;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strYhxh = tree.getSelected().key.substr(2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //window.open("../userAdm/editYh.do?yhxh="+strYhxh,"main");<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp; else if(tree.getSelected().key.substr(0,2)=="RB") {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdAddDept.disabled = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdAddPeople.disabled = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var strDwxh;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strDwxh = tree.getSelected().key.substr(2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //window.open("../userAdm/editBm.do?dwxh="+strDwxh,"main");<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp; else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdAddDept.disabled = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdAddPeople.disabled = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //window.open("yhroot.jsp","main");<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;}<BR>}</P>
<P>function addPeople() {<BR>&nbsp;&nbsp;&nbsp; var strDwxh;<BR>&nbsp;&nbsp;&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp; if (tree.getSelected().key.substr(0,2)=="RB") {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strDwxh = tree.getSelected().key.substr(2);<BR>&nbsp; //window.open("../userAdm/addYh.do?dwxh="+strDwxh,"main");<BR>&nbsp; alert("addPeople");<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}</P>
<P>function addDept() {<BR>&nbsp;&nbsp;&nbsp; var strDwxh;<BR>&nbsp;&nbsp;&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp; if (tree.getSelected().key.substr(0,2)=="RB") {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strDwfxh = tree.getSelected().key.substr(2);<BR>&nbsp; //window.open("../userAdm/addBm.do?dwfxh="+strDwfxh,"main");<BR>&nbsp;&nbsp;&nbsp; alert("addDept");<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(tree.getSelected().key=="R0") {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //window.open("../userAdm/addBm.do?dwfxh=0","main");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("addDept");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}</P>
<P>function deleSelected() {<BR>&nbsp; if(!confirm("确认删除该节点吗？"))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp; if(tree.getSelected().key.substr(0,2)=="RB") {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var strDwxh;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strDwxh = tree.getSelected().key.substr(2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //window.open("../userAdm/delBm.do?dwxh="+strDwxh,"main");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("deleSelected");<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else if(tree.getSelected().key.substr(0,2)=='RZ') {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var strYhxh,strYhbh;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strYhxh = tree.getSelected().key.substr(2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strYhbh = tree.getSelected().tag;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //window.open("../userAdm/delYh.do?yhxh="+strYhxh+"&amp;yhbh="+strYhbh,"main");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("deleSelected");<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp; }<BR>}</P>
<P>function removeNode() {<BR>&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp; var node = tree.getSelected();<BR>&nbsp;&nbsp;&nbsp; node.remove();<BR>&nbsp; }<BR>}</P>
<P>function addPeopleNode(strParentKey,strKey,strText,strTag) {<BR>&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp; var node = tree.getSelected();<BR>&nbsp;&nbsp;&nbsp; var childNode;<BR>&nbsp;&nbsp;&nbsp; //node.expand();<BR>&nbsp;&nbsp;&nbsp; childNode = node.add(new WebFXTreeItem(strText,strKey,strTag,"","","../resources/images/people1.png"));<BR>&nbsp;&nbsp;&nbsp; node.expand(); //why I do so? I dont want to tell you,hah!<BR>&nbsp;&nbsp;&nbsp; childNode.focus();<BR>&nbsp;&nbsp;&nbsp; treeClick();<BR>&nbsp; }<BR>}</P>
<P>function addDeptNode(strParentKey,strKey,strText,strTag) {<BR>&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp; var node = tree.getSelected();<BR>&nbsp;&nbsp;&nbsp; var childNode;<BR>&nbsp;&nbsp;&nbsp; childNode = node.add(new WebFXTreeItem(strText,strKey,strTag));<BR>&nbsp;&nbsp;&nbsp; node.expand();<BR>&nbsp;&nbsp;&nbsp; childNode.focus();<BR>&nbsp;&nbsp;&nbsp; treeClick();<BR>&nbsp; }<BR>}</P>
<P>function updateDeptNode(strTag,strText) {<BR>&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp; var node = tree.getSelected();<BR>&nbsp;&nbsp;&nbsp; node.text = strText;<BR>&nbsp;&nbsp;&nbsp; node.tag&nbsp; = strTag;<BR>&nbsp;&nbsp;&nbsp; node.focus();<BR>&nbsp; }<BR>}</P>
<P>function updatePeopleNode(strTag,strText) {<BR>&nbsp; if(tree.getSelected()) {<BR>&nbsp;&nbsp;&nbsp; var node = tree.getSelected();<BR>&nbsp;&nbsp;&nbsp; node.text = strText;<BR>&nbsp;&nbsp;&nbsp; node.tag&nbsp; = strTag;<BR>&nbsp;&nbsp;&nbsp; node.focus();<BR>&nbsp; }<BR>}<BR>&lt;/script&gt;<BR>&lt;%<BR>int dwxh;<BR>int dwfxh;<BR>int yhxh;<BR>String dwbh = null;<BR>String dwmc = null;<BR>String yhmc = null;<BR>String yhbh = null;<BR>int preLevel =1;<BR>int level = 1;<BR>DbAccess dbaccess = new DbAccess();<BR>String sql = "select dwxh,dwbh,dwmc,dwfxh from xt_dw order by dwbh";<BR>ResultSet rs = dbaccess.executeQuery(sql);<BR>try<BR>{<BR>&nbsp;while(rs.next())<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwxh = rs.getInt(1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwbh = rs.getString(2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwmc = rs.getString(3);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwfxh = rs.getInt(4);<BR>//通过单位编号计算level<BR>&nbsp; String last = dwbh.substring(9,10);<BR>&nbsp; int i = 9;<BR>&nbsp; while(last.equals("0") &amp;&amp; i&gt;0){<BR>&nbsp;&nbsp; i--;<BR>&nbsp;&nbsp; last = dwbh.substring(i,i+1);<BR>&nbsp; <BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; if(i==0 || i==1) level =1;<BR>&nbsp; if(i==2 || i==3) level =2;<BR>&nbsp; if(i==4 || i==5) level =3;<BR>&nbsp; if(i==6 || i==7) level =4;<BR>&nbsp; if(i==8 || i==9) level =5;<BR>//<BR>&nbsp; %&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;script type="text/javascript"&gt;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; nodeToAddPerson = addDeptTreeNode(&lt;%=preLevel%&gt;,&lt;%=level%&gt;,"&lt;%=dwmc%&gt;","RB&lt;%=dwxh%&gt;","&lt;%=dwbh%&gt;");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/script&gt;&nbsp; <BR>&nbsp; <BR>&nbsp; &lt;%<BR>&nbsp; preLevel = level;<BR>&nbsp; String subsql = "select yhxh,yhmc,yhbh from xt_yh where dwxh = "+Integer.toString(dwxh);<BR>&nbsp; ResultSet subRs = dbaccess.executeQuery(subsql);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(subRs.next()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yhxh = subRs.getInt(1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yhmc = subRs.getString(2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yhbh = subRs.getString(3); <BR>&nbsp; %&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;script type="text/javascript"&gt;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; nodeToAddPerson.add(new WebFXTreeItem("&lt;%=yhmc%&gt;","RZ&lt;%=yhxh%&gt;","&lt;%=yhbh%&gt;","","","../resources/images/people1.png"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/script&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;%<BR>&nbsp; }<BR>&nbsp; <BR>&nbsp;}<BR>&nbsp;dbaccess.closeStmt();<BR>&nbsp;dbaccess.closeConn();<BR>}<BR>catch(Exception e)<BR>{</P>
<P>}<BR>%&gt;</P>
<P><BR>&lt;base target="_self"&gt;<BR>&lt;META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE"&gt;<BR>&lt;/head&gt;<BR>&lt;body&gt;<BR>&lt;table border="0" width="100%" cellspacing="0" cellpadding="0"&gt;<BR>&nbsp; &lt;tr&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;td width="273" colspan="2"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;font face="宋体" size="3"&gt;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/font&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp; &lt;/tr&gt;<BR>&nbsp; &lt;tr&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;th width="33%" align="center" nowrap&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;p align="center"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;INPUT id=cmdAddDept name="AddDept" type=button value="增加部门" onclick="addDept()" style="FONT-FAMILY: 楷体_GB2312; FONT-SIZE: 12pt; FONT-WEIGHT: bold; HEIGHT: 24px; WIDTH: 80px" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/p&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/th&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;th width="33%" align="center" nowrap&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;p align="center"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;INPUT id=cmdAddPeople name="AddPeople" type=button value="增加用户" onclick="addPeople()" style="FONT-FAMILY: 楷体_GB2312; FONT-SIZE: 12pt; FONT-WEIGHT: bold; HEIGHT: 24px; WIDTH: 80px" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/p&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/th&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;th width="33%" align="center" nowrap&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;p align="center"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;INPUT id=cmdDelete name="Delete" type=button value=" 删除 " onclick="deleSelected()" style="FONT-FAMILY: 楷体_GB2312; FONT-SIZE: 12pt; FONT-WEIGHT: bold; HEIGHT: 24px; WIDTH: 80px" disabled&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/p&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/th&gt;<BR>&nbsp; &lt;/tr&gt;<BR>&nbsp; &lt;tr&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;td width="273" height="8"&nbsp; colspan="2"&gt;&amp;nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp; &lt;/tr&gt;<BR>&lt;/table&gt;<BR>&lt;/body&gt;<BR>&lt;div onclick="treeClick()"&gt;<BR>&lt;script type="text/javascript"&gt;&nbsp; <BR>&nbsp;document.write(tree);<BR>&lt;/script&gt;<BR>&lt;/div&gt;<BR>&lt;/HTML&gt;</P></TD></TR></TBODY></TABLE></SPAN></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/lq410/aggbug/15493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lq410/" target="_blank">扑扑</a> 2005-10-14 10:26 <a href="http://www.blogjava.net/lq410/archive/2005/10/14/15493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts-menu+ibatis+少量的代码=通用的自定义菜单和动态加载的树</title><link>http://www.blogjava.net/lq410/archive/2005/10/14/15490.html</link><dc:creator>扑扑</dc:creator><author>扑扑</author><pubDate>Fri, 14 Oct 2005 02:16:00 GMT</pubDate><guid>http://www.blogjava.net/lq410/archive/2005/10/14/15490.html</guid><wfw:comment>http://www.blogjava.net/lq410/comments/15490.html</wfw:comment><comments>http://www.blogjava.net/lq410/archive/2005/10/14/15490.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lq410/comments/commentRss/15490.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lq410/services/trackbacks/15490.html</trackback:ping><description><![CDATA[<P>前言：<BR>&nbsp;&nbsp;&nbsp;&nbsp;知识准备：首先你需要懂一些struts的基本知识，会用struts-menu，并理解站长对struts-menu的分析那篇文章，还要知道ibatis的基本知识，如果不懂，请去google或者站长的论坛里找相关的文章。</P>
<P>树形结构在实际开发中很常用，但是树形结构的开发往往也是难题，尤其是在显示这一条上，很难做到通用。通常有两种典型的树型结构。一种是论坛的帖子，其结构往往通过父子ID号相连,数据在一张表里。一种是级别，比如论坛中的Category-&gt;Forum-&gt;Thread这种结构，数据放在不同的表里。因为论坛恰好包含了这两种结构。因此。我们就能Jive的表结构来做这个例子。首先我们通过RsMetaDataTest来扫描数据库，得到需要的XML配置文件。拿一个xml为例，解释一下</P>
<TABLE width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#cccccc><PRE class="smallFont style2">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<BR>&lt;!DOCTYPE sql-map<BR>PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"<BR>"http://www.ibatis.com/dtd/sql-map.dtd"&gt;<BR>&lt;sql-map name="jivecategory"&gt;<BR>&lt;!-- =============================================<BR>    mapped-statement find <BR>============================================= --&gt;<BR>&lt;dynamic-mapped-statement name="findjivecategoryDao"  result-class="java.util.HashMap"&gt;<BR>   select $listfield$  from JIVECATEGORY<BR>   &lt;dynamic prepend="where"&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="CATEGORYID" &gt;<BR>         &lt;isNotNull prepend="" property="CATEGORYID" &gt;<BR>             CATEGORYID=#CATEGORYID#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="NAME" &gt;<BR>         &lt;isNotNull prepend="" property="NAME" &gt;<BR>             NAME=#NAME#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="DESCRIPTION" &gt;<BR>         &lt;isNotNull prepend="" property="DESCRIPTION" &gt;<BR>             DESCRIPTION=#DESCRIPTION#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="CREATIONDATE" &gt;<BR>         &lt;isNotNull prepend="" property="CREATIONDATE" &gt;<BR>             CREATIONDATE=#CREATIONDATE#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="MODIFIEDDATE" &gt;<BR>         &lt;isNotNull prepend="" property="MODIFIEDDATE" &gt;<BR>             MODIFIEDDATE=#MODIFIEDDATE#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="LFT" &gt;<BR>         &lt;isNotNull prepend="" property="LFT" &gt;<BR>             LFT=#LFT#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>      &lt;isPropertyAvailable prepend="and" property="RGT" &gt;<BR>         &lt;isNotNull prepend="" property="RGT" &gt;<BR>             RGT=#RGT#<BR>         &lt;/isNotNull&gt;<BR>      &lt;/isPropertyAvailable&gt;<BR>   &lt;/dynamic&gt;	  <BR>&lt;/dynamic-mapped-statement&gt;</PRE>
<P class="smallFont style2">&lt;/sql-map&gt;</P></TD></TR></TBODY></TABLE>
<P>可见有一个名叫f<SPAN class="smallFont style2"><FONT size=2>indjivecategoryDao</FONT></SPAN>，这是一个典型的动态查询。返回对象是HashMap。其中$listfield$表示动态读取的字段。可以这么说，通过这个查询。有关这样表的任何方式的查询都已经解决了。由于这个演示只用到四张表，因些我们在sql-map-config-storedb.xml也只加载了四张表的定义。</P>
<TABLE width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD>&lt;sql-map resource="sqlmap/jivecategory.xml" /&gt;<BR>&lt;sql-map resource="sqlmap/jiveforum.xml" /&gt; <BR>&lt;sql-map resource="sqlmap/jivethread.xml" /&gt; <BR>&lt;sql-map resource="sqlmap/jivemessage.xml" /&gt; </TD></TR></TBODY></TABLE>
<P>然后定义MenuDefine类，这个类是一个通用的定义，其主要属性如下。可以通过它建立一个四张表的树形关系。</P>
<TABLE width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><SPAN class=smallFont>//sql Map的名称 <BR>private String sqlMapName;<BR>//调用的查询名称<BR>private String SqlName;<BR>//子菜单的名称<BR>private String submenuName; </SPAN>
<P><SPAN class=smallFont>//对应字段，其中key为主表的字段，value是从表的字段。<BR>private HashMap keymap;<BR>//菜单的名称<BR>private String MenuName;<BR>//标题<BR>private String Title;<BR>//标题字段<BR>private String TitleField;<BR>//需要读取的字段<BR>private String listField;<BR>//是否需要显示<BR>private boolean needShow=true;</SPAN><BR></P></TD></TR></TBODY></TABLE>
<P>然后建立一个XML的文件(此处简化了它的功能，就是把上面这个类序列化了一下)。把它放在classes目录下。</P>
<TABLE width="100%" bgColor=#cccccc border=1><PRE>  </PRE>
<TBODY>
<TR>
<TD><PRE><FONT face=Arial><SPAN class=style3>&lt;?xml version="1.0" encoding="UTF-8"?&gt; <BR>&lt;java version="1.4.2_03" class="java.beans.XMLDecoder"&gt; <BR> &lt;object class="java.util.HashMap"&gt; <BR>  &lt;void method="put"&gt; <BR>   &lt;string&gt;message&lt;/string&gt; <BR>   &lt;object class="com.ewuxi.champion.MenuDefine"&gt; <BR>    &lt;void property="keymap"&gt; <BR>     &lt;object class="java.util.HashMap"&gt; <BR>      &lt;void method="put"&gt; <BR>       &lt;string&gt;MESSAGEID&lt;/string&gt; <BR>       &lt;string&gt;PARENTMESSAGEID&lt;/string&gt; <BR>      &lt;/void&gt; <BR>     &lt;/object&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="listField"&gt; <BR>     &lt;string&gt;MESSAGEID,SUBJECT&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="menuName"&gt; <BR>     &lt;string&gt;message&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlMapName"&gt; <BR>     &lt;string&gt;jivemessage&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlName"&gt; <BR>     &lt;string&gt;findjivemessageDao&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="submenuName"&gt; <BR>     &lt;string&gt;message&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="title"&gt; <BR>     &lt;string&gt;文章&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="titleField"&gt; <BR>     &lt;string&gt;SUBJECT&lt;/string&gt; <BR>    &lt;/void&gt; <BR>   &lt;/object&gt; <BR>  &lt;/void&gt; <BR>  &lt;void method="put"&gt; <BR>   &lt;string&gt;category&lt;/string&gt; <BR>   &lt;object class="com.ewuxi.champion.MenuDefine"&gt; <BR>    &lt;void property="keymap"&gt; <BR>     &lt;object class="java.util.HashMap"&gt; <BR>      &lt;void method="put"&gt; <BR>       &lt;string&gt;CATEGORYID&lt;/string&gt; <BR>       &lt;string&gt;CATEGORYID&lt;/string&gt; <BR>      &lt;/void&gt; <BR>     &lt;/object&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="listField"&gt; <BR>     &lt;string&gt;CATEGORYID,NAME&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="menuName"&gt; <BR>     &lt;string&gt;category&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlMapName"&gt; <BR>     &lt;string&gt;jivecategory&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlName"&gt; <BR>     &lt;string&gt;findjivecategoryDao&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="submenuName"&gt; <BR>     &lt;string&gt;forum&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="title"&gt; <BR>     &lt;string&gt;大分类&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="titleField"&gt; <BR>     &lt;string&gt;NAME&lt;/string&gt; <BR>    &lt;/void&gt; <BR>   &lt;/object&gt; <BR>  &lt;/void&gt; <BR>  &lt;void method="put"&gt; <BR>   &lt;string&gt;forum&lt;/string&gt; <BR>   &lt;object class="com.ewuxi.champion.MenuDefine"&gt; <BR>    &lt;void property="keymap"&gt; <BR>     &lt;object class="java.util.HashMap"&gt; <BR>      &lt;void method="put"&gt; <BR>       &lt;string&gt;FORUMID&lt;/string&gt; <BR>       &lt;string&gt;FORUMID&lt;/string&gt; <BR>      &lt;/void&gt; <BR>     &lt;/object&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="listField"&gt; <BR>     &lt;string&gt;FORUMID,NAME&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="menuName"&gt; <BR>     &lt;string&gt;forum&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlMapName"&gt; <BR>     &lt;string&gt;jiveforum&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlName"&gt; <BR>     &lt;string&gt;findjiveforumDao&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="submenuName"&gt; <BR>     &lt;string&gt;thread&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="title"&gt; <BR>     &lt;string&gt;子分类&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="titleField"&gt; <BR>     &lt;string&gt;NAME&lt;/string&gt; <BR>    &lt;/void&gt; <BR>   &lt;/object&gt; <BR>  &lt;/void&gt; <BR>  &lt;void method="put"&gt; <BR>   &lt;string&gt;thread&lt;/string&gt; <BR>   &lt;object class="com.ewuxi.champion.MenuDefine"&gt; <BR>    &lt;void property="keymap"&gt; <BR>     &lt;object class="java.util.HashMap"&gt; <BR>      &lt;void method="put"&gt; <BR>       &lt;string&gt;THREADID&lt;/string&gt; <BR>       &lt;string&gt;THREADID&lt;/string&gt; <BR>      &lt;/void&gt; <BR>      &lt;void method="put"&gt; <BR>       &lt;string&gt;FORUMID&lt;/string&gt; <BR>       &lt;string&gt;FORUMID&lt;/string&gt; <BR>      &lt;/void&gt; <BR>      &lt;void method="put"&gt; <BR>       &lt;string&gt;ROOTMESSAGEID&lt;/string&gt; <BR>       &lt;string&gt;MESSAGEID&lt;/string&gt; <BR>      &lt;/void&gt; <BR>     &lt;/object&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="listField"&gt; <BR>     &lt;string&gt;THREADID,ROOTMESSAGEID&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="menuName"&gt; <BR>     &lt;string&gt;thread&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="needShow"&gt; <BR>     &lt;boolean&gt;false&lt;/boolean&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlMapName"&gt; <BR>     &lt;string&gt;jivethread&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="sqlName"&gt; <BR>     &lt;string&gt;findjivethreadDao&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="submenuName"&gt; <BR>     &lt;string&gt;message&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="title"&gt; <BR>     &lt;string&gt;栏目&lt;/string&gt; <BR>    &lt;/void&gt; <BR>    &lt;void property="titleField"&gt; <BR>     &lt;string&gt;ROOTMESSAGEID&lt;/string&gt; <BR>    &lt;/void&gt; <BR>   &lt;/object&gt; <BR>  &lt;/void&gt; <BR> &lt;/object&gt; <BR>&lt;/java&gt; </SPAN><BR></FONT>
    </PRE></TD></TR></TBODY></TABLE>
<P>关联关系是<SPAN class=style3><FONT face=Arial>category</FONT></SPAN>表通过<SPAN class=style3><FONT face=Arial>CATEGORYID</FONT></SPAN>与<SPAN class=style3><FONT face=Arial>forum</FONT></SPAN>关联，<SPAN class=style3><FONT face=Arial>forum</FONT></SPAN>通过<SPAN class=style3><FONT face=Arial>FORUMID</FONT></SPAN>与<SPAN class=style3><FONT face=Arial>thread</FONT></SPAN>关联，<SPAN class=style3><FONT face=Arial>thread</FONT></SPAN>是一张特殊的表。它将不显示在树中，只是一个过渡关联，用于读出新建的文章。</P>
<P><SPAN class=style3><FONT face=Arial>thread</FONT></SPAN>通过<SPAN class=style3><FONT face=Arial>FORUMID</FONT></SPAN>、<SPAN class=style3><FONT face=Arial>FORUMID</FONT></SPAN>、<SPAN class=style3><FONT face=Arial>ROOTMESSAGEID</FONT></SPAN>与<SPAN class=style3><FONT face=Arial>message</FONT></SPAN>表关联(<SPAN class=style3><FONT face=Arial>FORUMID</FONT></SPAN>、<SPAN class=style3><FONT face=Arial>FORUMID</FONT></SPAN>、<SPAN class=style3><FONT face=Arial>MESSAGEID</FONT></SPAN>)。而message表是一个自关联的表。<SPAN class=style3><FONT face=Arial>MESSAGEID</FONT></SPAN>与<SPAN class=style3><FONT face=Arial>PARENTMESSAGEID</FONT></SPAN>关联建立父子关系。</P>
<P>然后我们建立一个session类作为主要类</P>
<TABLE width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#cccccc><PRE>public class TreeDemoSession {
	//通过名称和参数来得到树
	public MenuComponent getMenu(String name, Map keys) throws Exception {
		Map menuMap =
			(Map) (new XmlUtils().read(Service.getPath() + "/menu.xml"));
		MenuComponent menu = new MenuComponent();

		if (menuMap.get(name) != null) {
			MenuDefine rootMenudefine = (MenuDefine) menuMap.get(name);
			menu.setTitle(rootMenudefine.getTitle());
			menu.setName(rootMenudefine.getMenuName());

			menu = submenuAdd(menu, keys, menuMap, name);
		}
		return menu;
	}

	/**一个典型的递归函数。用以组织树。
	 * @param menu
	 * @param map
	 * @param menuMap
	 * @param menuName
	 * @return
	 * @throws DaoException
	 * @throws Exception
	 */
	private MenuComponent submenuAdd(
		MenuComponent menu,
		Map map,
		final Map menuMap,
		String menuName)
		throws DaoException, Exception {
		try {
			//得到菜单定义
			MenuDefine menudefine = (MenuDefine) menuMap.get(menuName);
			//listfield,表示需要读取哪几个字段
			map.put("listfield", menudefine.getListField());
			//查询，返回列表。
			List list = DaoCommon.findbyName(map, menudefine.getSqlName());

			int namei = 0;
			for (Iterator iter = list.iterator(); iter.hasNext();) {
				Map element = (Map) iter.next();
                //建立当前节点
				MenuComponent submenu = new MenuComponent();
				submenu.setName(menu.getName() + String.valueOf(namei++));
				submenu.setTitle(
					String.valueOf(element.get(menudefine.getTitleField())));
					//如果不需要显示，则使用父节点作为当前节点
				if (!menudefine.isNeedShow())
					submenu = menu;
				//如果有子菜单，则递归调用。	
				if (menudefine.getSubmenuName() != null) {

					submenu =
						submenuAdd(
							submenu,
							getSubMenuInfo(menudefine, element),
							menuMap,
							menudefine.getSubmenuName());
				}
				//将当前节点放到树中。(如果不需要显示就不用放)
				if (menudefine.isNeedShow())
					menu.addMenuComponent(submenu);
			}
			return menu;
		} catch (DaoException e) {

			throw e;
		} catch (Exception e) {

			throw e;
		}
	}

	/**将父菜单的关键字段的值作为参数给子菜单
	 * @param menudefine
	 * @param element
	 * @return
	 */
	private HashMap getSubMenuInfo(MenuDefine menudefine, Map element) {
		HashMap map = new HashMap();
		for (Iterator iter = menudefine.getKeymap().keySet().iterator();
			iter.hasNext();
			) {
			String key = (String) iter.next();
			map.put(menudefine.getKeymap().get(key), element.get(key));
		}
		return map;
	}
}&nbsp;</PRE></TD></TR></TBODY></TABLE>
<P>三个函数，非常简单，主函数读取配置文件的内容。一个递归函数用来建立树形结构。这棵树只有两个属性被设置。一个是名字和标题。其中标题采用从数据库里读出的字段。名字则采用流水号。读取数据库只有一句,其中map是参数的一个列表。后面是sql的名字。</P>
<TABLE width="100%" border=1>
<TBODY>
<TR>
<TD>List list = DaoCommon.findbyName(map, menudefine.getSqlName());</TD></TR></TBODY></TABLE>
<P>而真正的实现代码也非常简单</P>
<TABLE width="100%" border=1>
<TBODY>
<TR>
<TD>public static List findbyName(Object vo,String name) throws DaoException {<BR>try {<BR>SqlMap sqlMap = DaoCommon.getSqlMap(DaoCommon.getDefautDao());<BR>return (List) sqlMap.executeQueryForList(name, vo);<BR>} catch (Exception e) {<BR>throw new DaoException(e);<BR>}<BR>}</TD></TR></TBODY></TABLE>
<P>下面我们来做Action的工作</P>
<TABLE class=smallFont width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD>public ActionForward execute(<BR>ActionMapping mapping,<BR>ActionForm form,<BR>HttpServletRequest request,<BR>HttpServletResponse response)<BR>throws Exception { 
<P>Service.initSet();<BR>DaoCommon.startTransaction();</P>
<P>HashMap parMap = new HashMap();<BR>Enumeration enumeration = request.getParameterNames();<BR>while (enumeration.hasMoreElements()) {<BR>String element = (String) enumeration.nextElement();<BR>parMap.put(element, request.getParameter(element));<BR>}<BR>TreeDemoSession session=new TreeDemoSession();<BR>request.setAttribute("com.ewuxi.champion.menu",session.getMenu(request.getParameter("menuName"),parMap));</P>
<P>DaoCommon.rollBack();</P>
<P>return mapping.findForward(request.getParameter("type"));<BR>}<BR></P></TD></TR></TBODY></TABLE>
<P>这个函数也非常简单，就是把从request传来的内容生成一个Map对象。然后调用session,将返回结果以com.ewuxi.champion.menu为名字保存到request中去。</P>
<P>最后我们需要生成一个自定义的taglib。实际上很简单。只是因为struts-menu自身的taglib是写死了，我们不能利用，不过只要改一个地方就可以了,copy UseMenuDisplayerTag到我们的目录下。</P>
<TABLE width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD class=smallInput><SPAN class=smallFont>MenuRepository repository =<BR>(MenuRepository) pageContext.getServletContext().getAttribute(MenuRepository.MENU_REPOSITORY_KEY); </SPAN>
<P class=smallFont>if (repository == null) {<BR>throw new JspException("Could not obtain the menu repository");<BR>}</P>
<P class=smallFont>MenuComponent menu = repository.getMenu(this.name);</P></TD></TR></TBODY></TABLE>
<P>找到上面这一段，改成</P>
<TABLE width="100%" border=1>
<TBODY>
<TR>
<TD class=smallFont bgColor=#cccccc><BR>MenuComponent menu =<BR>(MenuComponent) pageContext.findAttribute(this.name);<BR></TD></TR></TBODY></TABLE>
<P>就OK了。然后需要建立一个JSP文件。我们把xtree.jsp借用过来。唯一需要改的就是&lt;cp:displayMenu name="com.ewuxi.champion.menu"/&gt;，当然还有几个link的路径。因为此处用treeDemo来所以就是href="/treeDemo/styles/xtree.css"</P>
<TABLE class=smallFont width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#cccccc>&lt;head&gt;<BR>&lt;title&gt;XTree (with Velocity) Example&lt;/title&gt; 
<P>&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;</P>
<P>&lt;link rel="stylesheet" type="text/css" media="screen"<BR>href="/treeDemo/styles/global.css" /&gt;<BR>&lt;link rel="stylesheet" type="text/css" media="screen"<BR>href="/treeDemo/styles/xtree.css" /&gt;<BR><BR>&lt;script type="text/javascript" src="/treeDemo/scripts/xtree.js"&gt;&lt;/script&gt;</P>
<P>&lt;/head&gt;<BR>&lt;body&gt;</P>
<P>&lt;div class="container"&gt;<BR>Simple menu with Velocity:&lt;br /&gt;<BR>&lt;script type="text/javascript"&gt;<BR>&lt;menu:useMenuDisplayer name="Velocity" config="/templates/xtree.html"<BR>bundle="org.apache.struts.action.MESSAGE"&gt;<BR>if (document.getElementById) {<BR>&lt;cp:displayMenu name="com.ewuxi.champion.menu"/&gt;<BR>} else {<BR>var msg = "Your browser does not support document.getElementById().\n";<BR>msg += "You must use a modern browser for this menu.";<BR>alert(msg);<BR>}<BR></P>
<P>&lt;/menu:useMenuDisplayer&gt;<BR>&lt;/script&gt;<BR>&lt;/div&gt;</P>
<P></P></TD></TR></TBODY></TABLE>
<P>下面就可以自由的看效果了。</P>
<TABLE width="100%" border=1>
<TBODY>
<TR>
<TD>&lt;p&gt;&lt;a href="demo.do?type=demo&amp;menuName=category" target="_blank"&gt;大分类列表&lt;/a&gt;<BR>&lt;/p&gt;<BR>&lt;p&gt;&lt;a href="demo.do?type=demo&amp;menuName=forum" target="_blank"&gt;子分类列表&lt;/a&gt; &lt;/p&gt;<BR>&lt;p&gt;&lt;a href="demo.do?type=demo&amp;menuName=forum&amp;FORUMID=1" target="_blank"&gt;只看java分类&lt;/a&gt; &lt;/p&gt;<BR>&lt;p&gt;&lt;a href="demo.do?type=demo&amp;menuName=thread" target="_blank"&gt;所有文章&lt;/a&gt; &lt;/p&gt;</TD></TR></TBODY></TABLE>
<P>上面是几种不同的参数。主要的差别是menuName不同。然后也可以加数据库需要的参数，比如java分类的forumId=1。就在参数中加FORUMID=1,注意大小写要跟XML中的动态参数相同，此处全是大写。</P>
<P>在线演示看这样<A href="http://demo.ewuxi.com:8000/treejivedemo/,源码下载%20http://champion.ewuxi.com/old/opensource/struts-new/treeDemo.rar">http://demo.ewuxi.com:8000/treejivedemo/,<BR>源码下载 <BR>http://champion.ewuxi.com/old/opensource/struts-new/treeDemo.rar</A><A href="http://www.cnblogs.com/ytfei/admin/treeDemo.rar"></A></P><!-- InstanceEndEditable --><img src ="http://www.blogjava.net/lq410/aggbug/15490.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lq410/" target="_blank">扑扑</a> 2005-10-14 10:16 <a href="http://www.blogjava.net/lq410/archive/2005/10/14/15490.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多对多关联</title><link>http://www.blogjava.net/lq410/archive/2005/09/23/13831.html</link><dc:creator>扑扑</dc:creator><author>扑扑</author><pubDate>Fri, 23 Sep 2005 05:59:00 GMT</pubDate><guid>http://www.blogjava.net/lq410/archive/2005/09/23/13831.html</guid><wfw:comment>http://www.blogjava.net/lq410/comments/13831.html</wfw:comment><comments>http://www.blogjava.net/lq410/archive/2005/09/23/13831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lq410/comments/commentRss/13831.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lq410/services/trackbacks/13831.html</trackback:ping><description><![CDATA[郁闷了好久的Hibernate的many-to-many双向关联搞定了<BR>
<P>在做hbiernate的many-to-many的双向关联时，一方要设置inverse="true"，另一方要设置inverse="false"。inverse="false"的一方保存时，维护多对多之间的关系，且只要将相互的关系告诉这一方即可。</P>
<P>如果inverse都设置为true，双方的关系将都不到维护。</P>
<P>如果都设置为false，双方将共同维护之间的关系，这时，要将双方的包含关系都要设置清楚，否则将会导致关系维护混乱。</P>
<P>如果设置了casade="save-update"，只能设置一方，如果双方都设置的话，当更新一方的时候，同时会更新另一方，另一方的更新又会导致一方的更新。<BR><BR>lazy loading指的是当实际要使用到某个数据字段时候，才将其从数据库中去出，避免内存的浪费。<BR><BR>inverse&nbsp;.&nbsp;inverse默认是false&nbsp;.当你指定inverse="true"&nbsp;cascade="none"&nbsp;&nbsp;时，这个实体对这个属性是没有持久更新的权利的，它把这个属性的管理权利完全交给了关联的另一方了。</P><img src ="http://www.blogjava.net/lq410/aggbug/13831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lq410/" target="_blank">扑扑</a> 2005-09-23 13:59 <a href="http://www.blogjava.net/lq410/archive/2005/09/23/13831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>