模拟数据库增删查改功能

xiaoxiao2021-02-28  105

1、 系统设计开发过程

数据库中有“表”的概念。“表”由若干“行”组成,每“行”由许多“列”组成。一般的数据库都提供了对SQL的支持。

我们可以模拟一个最简单版的SQL,只能实现简单的排序,简单的选择条件,列的显示顺序等功能。

输入help会打印出帮助信息。

可以使用下列命令序列测试它:

>load E:\\workspace\\data.txt >add A 11 22 33 44 >delete A B >update A length=11 weight=22 >update * A 22 33 44 55 >sort name >select length weight >select length weight where price>50 >select * where price>50 length<30 >exit

2、  主要功能模块的实现及调试过程

1.  创建信息类,信息包括名称(String)、长度(double)、重量(double)、威力(double)、price(double)。

class MyRow { private String name; // 名字 private double length; // 长度 private double weight; // 重量 private double power; // 威力 private double price; // 价格 public MyRow(String x) { String[] ss = x.split(" "); name = ss[0].trim(); length = Double.parseDouble(ss[1]); weight = Double.parseDouble(ss[2]); power = Double.parseDouble(ss[3]); price = Double.parseDouble(ss[4]); } public String toString() { return name+" "+length+" "+ weight+" " + power + " " + price; } public void SetName(String name){this.name=name;} public void SetLength(double length){this.length=length;} public void SetWeight(double weight){this.weight=weight;} public void SetPower(double power){this.power=power;} public void SetPrice(double price){this.price=price;} public String getName() { return name; } public double getLength() { return length; } public double getWeight() { return weight; } public double getPower() { return power; } public double getPrice() { return price; } }

2.主类,用来接收用户发送的命令,判断并把命令传给下一级处理类,得到返回值判断命令是否成功执行

public class Test { private static BufferedReader br_keyboard; static { // 将它用于从键盘读入 br_keyboard = new BufferedReader(new InputStreamReader(System.in)); } public static void main(String[] args) throws Exception { MyData data = new MyData(); MyCommand cmd = new MyCommand(data); // cmd 服务于 data for(;;)//一直执行,只能用户用exit命令退出程序 { System.out.print("请输入命令(输入help显示帮助信息):"); String s = br_keyboard.readLine(); if(s.equals("exit")) break; if(s.equals("help")){ System.out.println("----------------------------"); System.out.println("1.|load data.txt"); System.out.println(" |从当前目录装入文件data.txt,并显示"); System.out.println("2.|add A 11 22 33 44"); System.out.println(" |增加一条信息(名称A 长度11 重量22 威力33 价格44)到文件中,并显示"); System.out.println("3.|delete A B"); System.out.println(" |删除A和B的信息"); System.out.println("4.|update A length=11 weight=22"); System.out.println(" |把信息A的长度改为11,重量为22"); System.out.println("5.|update * A 22 33 44 55"); System.out.println(" |把信息A的长度、重量、威力、价格 改为22、33、44、55"); System.out.println("6.|sort name"); System.out.println(" |按“名称”排序,并显示"); System.out.println(" |类似地,还可以是 sort length, sort price,sortweight,sort power等"); System.out.println("7.|select length weight"); System.out.println(" |只显示 长度,重量两列"); System.out.println("8.|select length weight where price>50"); System.out.println(" |只显示长度,重量两列, 只包含价格 >50的行"); System.out.println("9.|select * where price>50 length<30"); System.out.println(" |显示所有列, 只包含价格>50 且 长度<30 的行"); System.out.println(" |其它的组合,从上边类推"); System.out.println("0.|exit"); System.out.println(" |退出程序"); System.out.println("----------------------------"); continue; } if(!cmd.execute(s)){ //调用下一级类中的函数进行命令的解析 System.out.println("无效的命令"); } } } }

3.命令解析类,把从主类传递过来的命令进行解析,判断命令对应的处理函数,把命令传给对应的函数。接收返回值并返回给Text类。

class MyCommand { private MyData data; public MyCommand(MyData x) { data = x; } public boolean execute(String x) throws IOException { int d = x.indexOf(" "); // 找第一个空格的位置 if(d<0) return false; String x1 = x.substring(0,d); String x2 = x.substring(d+1); if(x1.equals("load")){ if(!data.load(x2.trim())) System.out.println("装入文件出错!"); return true; } if(x1.equals("add")) return data.add(x2); if(x1.equals("delete")) return data.delete(x2); if(x1.equals("update")) return data.update(x2); if(x1.equals("sort")) return data.sort(x2.trim()); if(x1.equals("select")) return data.select(x2); return false; } }

4.处理类,处理各种命令,返回处理结果

class MyData { // 内部类,“裁判”类,用于裁决Vector中的对象的比较大小问题 class Bijiao implements Comparator<MyRow> { private int type; //保存需要比较的信息的序号。例如:1,表示name;2,表示length…… public Bijiao(int type) { this.type = type; } public int compare(MyRow o1,MyRow o2) //比较的规则 { if(!(o1 instanceof MyRow)) return 0; //判断传递过来的信息是否是MyRow类 if(!(o2 instanceof MyRow)) return 0; MyRow r1 = (MyRow)o1; MyRow r2 = (MyRow)o2; switch(type){ case 1: if(r1.equals(r2)) return 0; else if(r1.getName().compareTo(r2.getName())<0) //name大小排列,小->大 return -1; else return 1; case 2: if(r1.equals(r2)) return 0; else if(r1.getLength()<r2.getLength()) //length大小排列,小->大 return -1; else return 1; case 3: if(r1.equals(r2)) return 0; else if(r1.getWeight()<r2.getWeight()) //weight大小排列,小->大 return -1; else return 1; case 4: if(r1.equals(r2)) return 0; else if(r1.getPower()<r2.getPower()) //power大小排列,小->大 return -1; else return 1; case 5: if(r1.equals(r2)) return 0; else if(r1.getPrice()<r2.getPrice()) //price大小排列,小->大 return -1; else return 1; default: return 0; } } } private List<MyRow> _v = new Vector<MyRow>(); //保存所有的信息 //在屏幕上显示信息 public void show() { System.out.println("...................................."); System.out.println("名称 长度 重量 威力 价格"); for(int i=0; i<_v.size(); i++){ System.out.println(_v.get(i)); } System.out.println("...................................."); } File file=null; //全局变量保存路径 //加载文件信息,读取->保存->show() public boolean load(String x) //x为一个路径 { try{ if(!x.equals("syh")) //判断加载时否是用户主用命令加载 { this.file=new File(x); } BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file))); _v.clear(); //清空_v,防止二次加载时_v中有之前保存的数据 br.readLine(); // 第一行不要 String s=""; while((s = br.readLine())!=null){ _v.add(new MyRow(s)); } br.close(); show(); //显示到屏幕 return true; } catch(Exception e){ return false; } } //添加信息,先在链表中添加,然后写入文件然后加载 public boolean add(String x) //x:A 11 22 33 44 { try{ String[] ss = x.split(" "); String name = ss[0].trim(); x=ss[0]+" "+ss[1]+" "+ss[2]+" "+ss[3]+" "+ss[4];//把数组x改为MyRow()可以分解的数组 if((check(name))==0) //判断添加的信息是否已经存在 { _v.add(new MyRow(x)); }else{ System.out.println("您增加的信息重复"); return true; } Write(); load("syh"); //非用户主动用命令加载信息,读取路径为用户用命令时的路径 return true; }catch(Exception e){ return false; } } //按name查找某条信息,返回该信息下标+1 public int check(String s) { for(int i=0;i<_v.size();i++) { MyRow row = (MyRow)_v.get(i); if(s.equals(row.getName())) return (i+1); //返回该信息的位置+1是因为防止该信息为下标为0 } return 0; //信息不存在直接返回0 } //把信息重新写到文件中 public void Write() { try { Writer out=new FileWriter(file); out.write("名称 长度 重量 威力 价格"); for(int i=0;i<_v.size();i++) { MyRow row = (MyRow)_v.get(i); out.write("\r\n"+row.getName()+" "+row.getLength()+" "+row.getWeight()+" "+row.getPower()+" "+row.getPrice()); } out.close(); } catch (Exception e) { e.printStackTrace(); } } //删除某几条信息,先删除链表中的信息,然后再文件中写入,然后再加载 public boolean delete(String x) //x:A B { try{ String[] ss = x.split(" "); int j; for(int i=0;i<ss.length;i++) if((j=check(ss[i]))!=0) { _v.remove(j-1); } Write(); load("syh"); return true; }catch(Exception e){ return false; } } //更新信息,先更新链表中的信息->把全部信息写入文件->加载 public boolean update(String x) //x:A length=11 weight=33或者* A 11 22 33 44 { try { String ss[]=x.split(" "); boolean flag=true; //判断更新的信息是否更新,如没更新,则说明该信息不存在 for(int i=1;i<ss.length;i++) { String[] ssa=ss[i].split("="); int j=0; if((j=check(ss[0]))!=0) //当x为A length=11 weight=33,即部分更新的情况 { flag=false; if(ssa[0].equals("length")) _v.get(j-1).SetLength(Double.parseDouble(ssa[1])); if(ssa[0].equals("weight")) _v.get(j-1).SetWeight(Double.parseDouble(ssa[1])); if(ssa[0].equals("power")) _v.get(j-1).SetPower(Double.parseDouble(ssa[1])); if(ssa[0].equals("price")) _v.get(j-1).SetPrice(Double.parseDouble(ssa[1])); } } if(ss[0].equals("*")) //当x为* A 11 22 33 44,即全部更新情况 { int j; if((j=check(ss[1]))!=0) { flag=false; _v.get(j-1).SetLength(Double.parseDouble(ss[2])); _v.get(j-1).SetWeight(Double.parseDouble(ss[3])); _v.get(j-1).SetPower(Double.parseDouble(ss[4])); _v.get(j-1).SetPrice(Double.parseDouble(ss[5])); } } if(flag) { System.out.println("不存在您要更新的内容"); return true; } Write(); load("syh"); return true; }catch (Exception e) { return false; } } //排序 public boolean sort(String x) //x可为name或者lengt或者weight…… { if(x.equals("name")){ Collections.sort(_v, new Bijiao(1)); //1表示名称,类似2为长度…… show(); return true; } if(x.equals("length")){ Collections.sort(_v, new Bijiao(2)); show(); return true; } if(x.equals("weight")){ Collections.sort(_v, new Bijiao(3)); show(); return true; } if(x.equals("power")){ Collections.sort(_v, new Bijiao(4)); show(); return true; } if(x.equals("price")){ Collections.sort(_v, new Bijiao(5)); show(); return true; } return false; } // 筛选需要显示的信息,把筛选命令分解 public boolean select(String x) //x:select weight length或者select weight length where price>50或者 select * where price>50 length<30 { Vector<String> sort = new Vector<String>(); // 保存需要显示的信息 Vector<String> where = new Vector<String>(); // 保存过滤的条件即where后面的字符 String[] ss = x.split(" "); Vector<String > t = sort; for(int i=0; i<ss.length; i++){ if(ss[i].length()==0) continue; // 防止多个空格 if(ss[i].equals("where")){ t = where; continue; } t.add(ss[i]); } if(sort.size()==0) return false; // 字段必须指定 if(sort.size()>5) return false; // 字段太多 return select(sort, where); } // 执行select任务 public boolean select(Vector<String> sort,Vector<String> where) { try{ System.out.println("...................................."); //输出标题 System.out.print("名称 "); for(int k=0; k<sort.size(); k++){ // 枚举sort if(sort.get(k).equals("length")) System.out.print("长度 "); else if(sort.get(k).equals("weight")) System.out.print("重量 "); else if(sort.get(k).equals("power")) System.out.print("威力 "); else if(sort.get(k).equals("price")) System.out.print("价格 "); else if(sort.get(k).equals("*")) System.out.print("长度 重量 威力 价格 "); else return false; } System.out.println(""); for(int i=0; i<_v.size(); i++){ //输出内容 MyRow row = (MyRow)_v.get(i); if(checkWhere(row, where)){ System.out.print(row.getName() + " "); for(int k=0; k<sort.size(); k++){ if(sort.get(k).equals("length")) System.out.print(row.getLength() + " "); else if(sort.get(k).equals("weight")) System.out.print(row.getWeight() + " "); else if(sort.get(k).equals("power")) System.out.print(row.getPower() + " "); else if(sort.get(k).equals("price")) System.out.print(row.getPrice() + " "); else if(sort.get(k).equals("*")) System.out.print(row.getLength()+" "+row.getWeight()+" "+row.getPower()+" "+row.getPrice()); else return false; } System.out.println(""); } } System.out.println("...................................."); return true; } catch(Exception e){ //e.printStackTrace(); return false; } } // 返回true 则该行记录显示,返回false,则不显示 public boolean checkWhere(MyRow row, Vector<String > where) throws Exception { boolean op=true; // true: 表示比较符号为 > , 否则为 < String field = ""; // 过滤条件的字段 String value = ""; // 过滤值 // 对每一个条件处理 for(int i=0; i<where.size(); i++){ String s = (String)where.get(i); String[] ss = s.split(">"); if(ss.length==2){ field = ss[0]; op = true; value = ss[1]; } else{ ss = s.split("<"); if(ss.length==2){ field = ss[0]; op = false; value = ss[1]; } else return false; // 既没有"<"也没有">"的情况 } double d_value = Double.parseDouble(value); if(field.equals("length")){ if(op){ if(row.getLength() <= d_value) return false; } else{ if(row.getLength() >= d_value) return false; } } else if(field.equals("weight")){ if(op){ if(row.getWeight() <= d_value) return false; } else{ if(row.getWeight() >= d_value) return false; } } else if(field.equals("power")){ if(op){ if(row.getPower() <= d_value) return false; } else{ if(row.getPower() >= d_value) return false; } } else if(field.equals("price")){ if(op){ if(row.getPrice() <= d_value) return false; } else{ if(row.getPrice() >= d_value) return false; } } else throw new Exception("valid field name!"); // 无法识别的 field,则算错表达式错 } return true; } }

3、  系统存在的不足

在对数据进行增(add)、删(delete)、改(update)时,先对从文件读取的数据进行修改,然后重新写入文件然后再读取显示到屏幕中。这种操作在数据量较小时处理的时间比较短,但随着数据量的增加处理的时间就会急剧增加,假如修改一个数据需要时间为x,往文件中写入一个数据需要时间为y,从文件中读取一个数据时间为z,则增加一条数据则用时为:(x+(n+1)*y+(n+1)*z)。若直接在文件中进行增加一条数据则用时为:(y+(n+1)*z)。这样比较就显示出程序的效率太低,需要改进。还有就是只能对特定的表进行操作,比如如果表的属性不是 名称(String)、长度(double)、重量(double)、威力(double)、price(double),则功能就不能实现,但是该缺点易改进,使用Map进行匹配就可以实现对任意表进行操作。

源码  下载地址

转载请注明原文地址: https://www.6miu.com/read-23112.html

最新回复(0)