- 浏览: 58257 次
- 性别:
- 来自: Southeast University
最近访客 更多访客>>
最新评论
-
truebit:
把引用Xq@a*4存成文件viPlugin.license保持 ...
破解了下ViPlugin -
niejieqiang:
博主,您好,我在MyEclipse上用Viplugin宏操作的 ...
破解了下ViPlugin -
flyrambler:
可以的话,我也想要一下试试, hu_zf@163.com,谢谢 ...
破解了下ViPlugin -
yanzixiang:
我想要,发一下吧,yanzixiangnande@gmail. ...
破解了下ViPlugin -
ouspec:
加油
儿童节礼物
我的标题真冗长:P
最近一直在考虑这个问题,如何在现在常用的关系型数据库(如mysql,mssql)中存储含有层次结构(例如xml或者树型结构)的数据,我最终要实现的结果是一个比较好的页面三级联动菜单。比较了一下现有的三级联动,无非有两种解决方案,1、将所有数据写成静态的,这样的缺点在于对更新封闭;2、每改变一次去数据库中获取数据,填充到下一级菜单,这个缺点是对数据库的开销比较大,查询一次数据要对数据库做三次操作,而且数据库设计的比较丑陋。上述两种方法都让我比较不能接受。
我想的是一种比较优雅的解决方案:在数据库中存储的数据不要冗余,便于查询,不要产生递归,对数据库的开销要尽可能的小,尽量做到一次将所有数据都读出来,用户也要有比较好的体验。我最初的解决方案就是用xml来存储联动的数据,但是对于数据库操作来说,最后还是要落实到对文件的I/O操作,从这方面来讲,使用xml和数据库并没有什么本质的不同。另外一种解决方案就是在关系数据库中存类xml的数据了。google了半天,最后发现了一片自己学院一位学长翻译的文章www.nirvanastudio.org/category/database,讲得就是如何在关系型数据库存储这种层次数据的。文中提出了两种解决方案,一是“邻接列表模型”或称为“递归方法”,这种存在着数据冗余,而且递归出于众所周知的原因,效率不高。第二种方法,也就是我现在采用的方法是"前序优先遍历",表结构也很简单,没有冗余
id | name | left | right |
我觉得应该属于一种深度优先。通过每个节点的左右两个属性获得其子女的属性,好处就在于获得一个或几个节点只需要一次查询,而在更新的时候速度会比较慢,因为要更新多个后继节点,不过话说回来,更新相对于获取来说次数要少的多,可以忽略。
下面是我的解决方案:
java 代码
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.util.ArrayList;
- import com.netkc.struts.datasource.DataSource;
- import com.netkc.struts.mapping.District;
- /**
- * @author SONG Yihan
- * @version 1.0
- * @date: Monday, April 09 2007
- */
- public class DistrictTree {
- private ArrayList<district> tree; </district>
- private Statement stmt1 = null;
- private Statement stmt2 = null;
- private Connection conn = null;
- private ResultSet rs = null;
- public DistrictTree() {
- try {
- conn = DataSource.getConnection();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- public DistrictTree(Connection conn) {
- this.conn = conn;
- }
- public boolean addNode(String parentId, String districtId, String districtName) {
- try {
- String sql = "SELECT * FROM district WHERE districtId='" + parentId + "';";
- conn.setAutoCommit(false);
- stmt1 = conn.createStatement();
- rs = stmt1.executeQuery(sql);
- if(rs.next()) {
- int right = rs.getInt("rgt");
- sql = "UPDATE district SET lft=lft+2 WHERE lft>=" + right;
- stmt2.addBatch(sql);
- sql = "UPDATE district SET rgt=rgt+2 WHERE rgt>=" + right;
- stmt2.addBatch(sql);
- sql = "INSERT INTO district (districtId, districtName, lft, rgt) VALUES ('"+districtId + "', '" + districtName + "', " +
- (right) + ", " + (right+1) +");";
- stmt2.addBatch(sql);
- int[] flag = stmt2.executeBatch();
- if(flag[flag.length - 1] == 1) {
- conn.commit();
- return true;
- } else {
- conn.rollback();
- return false;
- }
- }
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- }
- return false;
- }
- public boolean deleteNode(String districtId) {
- String sql = "SELECT * FROM district WHERE districtId='" + districtId + "';";
- try {
- conn.setAutoCommit(false);
- rs = stmt1.executeQuery(sql);
- if(rs.next())
- {
- int left = rs.getInt("lft");
- int right = rs.getInt("rgt");
- int count = (right - left - 1) / 2 + 1;
- int minus = count * 2;
- sql = "DELETE FROM district WHERE lft BETWEEN " + left + " AND " + right + ";";
- stmt2.addBatch(sql);
- sql = "UPDATE district SET lft=lft-" + minus + " WHERE lft>"+right;
- stmt2.addBatch(sql);
- sql = "UPDATE district SET rgt=rgt-" + minus + " WHERE rgt>"+right;
- stmt2.addBatch(sql);
- int flag = stmt2.executeBatch()[0];
- if(flag == 1) {
- conn.commit();
- return true;
- } else {
- conn.rollback();
- return false;
- }
- }
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return false;
- }
- public void displayTree(String parentId) {
- }
- public ArrayList<district> getTree(String parentId) { </district>
- String sql = "SELECT * FROM district WHERE districtId='" + parentId + "';";
- try {
- stmt1 = conn.createStatement();
- rs = stmt1.executeQuery(sql);
- if(rs.next()) {
- int left = rs.getInt("lft");
- int right = rs.getInt("rgt");
- stmt2 = conn.createStatement();
- sql = "SELECT * FROM district WHERE lft BETWEEN " + left + " AND " + right + " ORDER BY lft ASC";
- rs = stmt2.executeQuery(sql);
- tree = new ArrayList<district>(); </district>
- District district = null;
- while(rs.next()) {
- district = new District();
- district.setDistrictId(rs.getString("districtId"));
- district.setDistrictName(rs.getString("districtName"));
- district.setLeft(rs.getInt("lft"));
- district.setRight(rs.getInt("rgt"));
- tree.add(district);
- }
- return tree;
- }
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) {
- rs.close();
- }
- stmt1.close();
- stmt2.close();
- conn.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return null;
- }
- public ArrayList<district> getChildren(String parentId) { </district>
- if(tree == null) {
- tree = getTree(parentId);
- }
- ArrayList<district> children = new ArrayList<district>(); </district></district>
- int index = this.indexof(parentId);
- if(index != -1) {
- District d = tree.get(index);
- final int count = (d.getRight() - d.getLeft() - 1) / 2;
- for(int i = index + 1; i <= index + count; i++) {
- d = tree.get(i);
- children.add(d);
- i += (d.getRight() - d.getLeft() - 1) / 2;
- }
- }
- return children;
- }
- private int indexof(String districtId) {
- for(int index = 0; index < tree.size(); index++) {
- if(districtId.equals(tree.get(index).getDistrictId())) {
- return index;
- }
- }
- return -1;
- }
- public boolean updateNode(String districtId, String districtName) {
- String sql = "UPDATE district SET districtName='" + districtName + "' WHERE districtId='" + districtId + "';";
- try {
- conn.setAutoCommit(false);
- stmt1 = conn.createStatement();
- int flag = stmt1.executeUpdate(sql);
- if(flag == 1) {
- conn.commit();
- return true;
- }
- else {
- conn.rollback();
- return false;
- }
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- }
- return false;
- }
- }
这个最遗憾的地方就是在其中混杂了java代码,这让我及其不爽,但是我没有找到向js传值的好办法:(
- function District(id, name, left, right) {
- this.id=id;
- this.name=name;
- this.left=left;
- this.right=right;
- };
- var tree = new Array();
- <%
- for(District d : tree) {
- %> tree.push(new District('<%=d.getDistrictId()%>', '<%=d.getDistrictName()%>', '<%=d.getLeft()%>', '<%=d.getRight()%>'));
- <%}%>
- Array.prototype.indexof = function(id) {
- for(var index = 0; index < tree.length; index++) {
- if(id == tree[index].id) {
- return index;
- }
- }
- return -1;
- };
- function citychanged(id){
- document.getElementById('district').length = 0;
- document.getElementById('area').length = 0;
- var districts = getChildren(id);
- for(var i = 0; i < districts.length; i++){
- document.getElementById('district').options[i] = new Option(districts[i].name, districts[i].id);
- }
- };
- function districtchanged(id) {
- document.getElementById('area').length = 0;
- var area = getChildren(id);
- for(var i = 0; i < area.length; i++){
- document.getElementById('area').options[i] = new Option(area[i].name, area[i].id);
- }
- };
- function getChildren(id) {
- if(tree.length == 0) {
- }
- var children = new Array();
- var index = tree.indexof(id);
- if(index != -1) {
- var d = tree[index];
- var count = (d.right - d.left - 1) / 2;
- for(var i = index + 1; i <= index + count; i++) {
- d = tree[i];
- children.push(d);
- i += (d.right - d.left - 1) / 2;
- }
- }
- return children;
- };
- "/fastfoodAct?method=query" styleId="queryFoodForm">
- searchType :
- city :
-
- district :
-
- area :
-
- restaurantName :
- searchType :
- foodName :
- <html:submit> <html:cancel> </html:cancel> </html:submit>
以上就是我解决三级联动和层次结构的一点想法:)
发表评论
-
HashMap,Hashtable,HashSet等等Hash Collection之间的区别
2007-05-25 13:00 7947昨天博奥杰面试的时候,pm问了我一个问题,HashMap与Ha ... -
java到底是传值还是传引用
2007-05-23 22:42 2541这个很基础很基础的问题今天才搞明白。 今天和同学讨论C++的一 ... -
如何ie6下utf8的页面传递中文参数
2007-05-14 22:51 5294今天遇到了一个问题,就是明明在ff和opera下都很正常的链接 ... -
如何使用jstl只获取数组中的某些项
2007-04-29 02:38 4291我原以为可以直接修改<c:foreach>中的步长 ... -
Linux下MySQL,jsp的中文问题解决
2007-03-11 17:05 2626我的环境为Ubuntu 6.10, MySQL 5.0.24a ... -
在linux下进行java分布式编程
2007-03-09 20:54 2093最近在上分布式的课,由于打开orbd服务需要监听900端口,而 ...
相关推荐
首先,SQL数据库在这里扮演了存储角色,它包含了中国所有省份、城市和区县的层次关系数据。通常,这样的数据结构会设计成树形,每个节点代表一个行政区域,包含自身的ID、名称和上级ID。例如,"北京市"可能有一个ID...
在Android开发中,"RecyclerView三级联动"是一种常见的交互设计,尤其在展示层级关系的数据时,如商品分类、地区选择等场景。RecyclerView作为Android系统提供的一个高效、可复用的列表视图,能够处理大量数据并提供...
表中的数据结构通常是树形的,通过parent_id来建立层级关系。在设计数据库时,要考虑如何高效地查询各级数据,比如使用索引优化查询速度。 在部署这个项目时,需要注意以下几点: 1. 数据库配置:确保PHP连接到正确...
2. 数据填充:在应用启动时,会有一个初始化过程,从数据库读取所有省市区数据,并构建一个树形结构的数据模型。这个模型可以是自定义的类,包含子节点列表,便于在联动菜单中使用。 3. Spinner适配器:每个Spinner...
这通常是一个树形结构,例如HashMap或者自定义的类,包含父节点和子节点的关系。在用户选择一个节点时,根据这个节点的ID获取其子节点数据。 5. 动态加载:为了优化性能,通常不会一次性加载所有级别的数据。只有在...
1. 数据结构设计:一般会使用树形结构(如HashMap或自定义类)存储省市区数据,方便根据父级ID查询子级数据。 2. 数据加载:通过网络请求或者本地数据库获取省市区数据。 3. 视图渲染:`WheelView`的适配器(Adapter...
在IT领域,"省市区三级联动Dialog"是一个常见的交互设计元素,主要应用于用户需要选择地理位置信息的场景,如填写收货地址、设置定位等。这种设计通常涉及到前端开发中的下拉选择框(Dropdown)或者对话框(Dialog)...
在这个实例中,它会包含省市县的层级数据,可能以树形结构存储,每级地区对应一个表,或者所有地区信息存放在一个表内,通过父级ID关联。 资源包中的SQL文件很可能包含了创建数据库表和初始化数据的脚本。可能的表...
3. **数据库操作**:为了实现三级联动,需要数据库存储地区信息,并设计合适的数据库表结构,比如一个包含省、市、区县的树形结构。此外,需要编写SQL查询语句或使用ORM(对象关系映射)工具来获取数据。 4. **批量...
在实现三级联动地址选择器时,我们通常会在ListView中创建自定义的Adapter,这个Adapter负责将数据转化为ListView可以显示的View。每个View代表一个地址选项,如省份、城市或区县。 接下来,我们需要准备地址数据。...
数据库表的设计应考虑如何有效地存储和查询这些数据,例如,可以使用树形结构或者父ID字段来表示层级关系。 9. **HTTP协议**:Ajax请求通过HTTP协议发送到服务器,请求中包含了请求方法(GET或POST)、URL、请求头...
在易语言中,"多级联动"是一个常见的概念,通常应用于数据筛选、下拉菜单或者树形结构的交互设计中。 多级联动的核心在于各个级别之间的关联和互动。例如,在一个组织架构中,可能有省份、城市、区县的三级联动选择...
分页列表、树形、面包屑、三级联动、内容格式化。 4.2. 举几个简单模块的例子 4.2.1. 品牌管理 单表 分页、新增、删除、修改 4.2.2. 规格管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) ...
3. **SQL数据库**:在实现省市区三级联动时,后台通常使用SQL(Structured Query Language)数据库存储和管理省市区数据。这些数据可能存储在一个或多个表中,每个级别对应一个字段,通过外键关联形成层级关系。 4....
4. **数据库设计**:在数据库层面,省市区数据可能存储在一个表中,包含省份、城市和区县三个字段,或者采用分级的树形结构,每个区域有自己的父级ID,便于构建多级联动效果。 5. **JSON格式**:后端返回的数据通常...
在Android开发中,省市区三级联动是一个常见的需求,特别是在实现地址选择功能时。这个压缩包“Android 省市区三级连动--spinner.rar”显然包含了实现这一功能的相关代码和资源。接下来,我们将深入探讨如何在...
- 在这个源码中,数据结构可能是以树形结构表示的,包含省份、城市和区县的嵌套列表。每个节点可能包含自己的ID、名称以及子节点列表。 - 数据可能以JSON格式存储,便于加载和解析。 3. **SQLite数据库存储**: ...
2. "51aspx省市区县(含全国完整数据库)Ajax无刷新三级联动":这个文件名揭示了项目的具体实现细节。51aspx 是一个 ASP.NET 技术交流平台,这里提到的可能是该平台上的一个示例或教程。文件包括了全国的省市区县数据...
这通常是一个多级树形结构,每个节点代表一个地区,包含地区ID、名称以及子地区的列表。可以使用JSON格式存储,便于解析和加载。 2. **数据加载**:从服务器获取地区数据,或者在本地存储预加载好的数据,根据应用的...
- 三级联动的数据结构通常采用树形结构,如HashMap或自定义类,包含省份、城市和区县的ID和名称,每个父节点包含子节点的列表。 3. **数据获取与管理**: - 数据来源:可从网络API获取,也可以预设在应用内。例如...