数据库表结构的新论术
虚拟表:
我们把一个字符串看成是一张表的的行为长为虚拟表: 命名 Table
我们设计一个可以增删改查的类,把添加到的数据制作成表的操作,叫虚拟表操作 命名TableMake 数据最终生成一个表格式的字符串 V <-生成|
| |
->进行保存 ----> 提取--V |
我们设计另一个类,将字符串拆解成一张表的行为,叫解析字符串,当然,这个字符串的组成必须按照特定的格式 命名TableRead 将一个表格式字符串分解成一张表 -------- |
TableMake类 和TableRead类
一TableMame类
package com.df; import java.io.Serializable; /** * 一部份 TableMake类 的介绍 * * 虚拟表: TableMake * 我们将一个字符串看成是一张表 * 然后我们就可以对这个字符串以表的型式进行添加一行,删除一行,修改一行,或是修改表格中的数据,简称表的操作 * * 最后还可以保存这个字符串到数据库中表中的一个字符串型式的字段中, 通过TableRead 来将这个字符串分解释成一个 TableMake * * 当我们使用这个字符串时,通过分解类又将这个字符串分解成 虚拟表又可进行操作 * * 一 使用TableMake 创建一个虚拟表 * 第一步 : * 声明对象: * TableMake tableMake= new TableMake(); * 设置表头: * tableMake.setTypes("姓名","年龄","性别"); * 添加一行 * tableMake.addRow("小明",19,"女"); * tableMake.addRow("小芳",18,"男"); * * String table=tableMake.toTable(); * table是被格式化的 String * table格式化后: * 输出table: *<ts><t>姓名</t><t>年龄</t><t>性别</t></ts> *<rs> * <r><i>小明</i><i>19</i><i>女</i></r> * <r><i>小芳</i><i>18</i><i>男</i></r> *</rs> * * 标签说明: *<ts></ts> <ts>=types 所有字段的开头 </ts> 表中的所有字段到这里结束 *<t></t> t= 字段 *<rs></rs> rs= rows *<r> </r> r= row *<i></i> = item 表示一个行中的一个数据 * * * 二 手写 TableMake 格式字符串 添加的创建字段 和数据中不包函的字符串 标签总表: 1 <ts> 代表 表头的开始 系统识别表头的开始 2 </ts> 代表 表头的结速 系统识别表头的结速 3 <t> 代表 一个字段的开始 系统识别一个字段的开始 4 </t> 代表 一个字段的结束 系统识别一个字段的结束 5 <rs> 代表 所有行的开始 系统识别所有行的开始 6 </rs> 代表 所有行的结束 系统识别所有行的结束 7 <r> 代表一行的开头 系统识别一行的开头 8 </r> 代表一行的结束 系统识别一行的结束 9 <i> 代表一行中一个数据的开始 系统识别一行中一个数据的开始 10</i> 代表一行中一个数据的结束 系统识别一行中一个数据的结束 三手写 标签包函规则 1<ts> ... </ts> 1 只能包函 <t> </t> 2 一个表只允许一对<ts> ... </ts> 2<t></t> 1 只能包函 String 类型 2 不能包函标签总表10个标签之一 2<rs> </rs> 1 只能包函 <r></r> 2 一个表只允许一对<rs> </rs> 3<r> ... </r> 1 只能包函<i></i> 2 <rs></rs> 可以包函无数个 <r></r> 4<i></i> 1 在一对<r></r> 里面包函<i></i>的数量 ,只能永远保持 和<t></t> 的数量对应 : 例如 <ts><t>好友</t><t>手机号码</t></ts> 包函2个 那么一个<r><i>小明</i><i>13580150692</i></r> 只能包函2个<i></i> 2<i></i>的包函数据的范围 1 String 2 所有java的number子类 3 boolean 四 数据库表中的默认值示例为 <ts><t>好友</t>年龄<t></t><t>电话</t><t>姓别</t><t>备注</></ts> <rs> </rs> * * * *二部份 解释TableRead * 创建 TableRead 来解释这张表 * Table(String table); * * TableRead tableRead = new TableRead(); * tableRead.setTable(table); //读取table字符串 * String[] types=tableRead.getTypes(); //分解出表中的所有字符 * Object[] rows=tableRead.getRows(); //分解出表中的所有行 * Object data=tableRead.get(int rowIndex, int coulmnIndex); //分解出表中一个位置的数据 * * TableMake toMake=tableRead.toTableMake(); // 将字table 重新组成一个虚拟表 可以对table又进行以表的型式进行增删改查了 * *三扩展:因为tableRead 是源代码,所以可以自由扩展,例 可以扩展sql 语句查询这个对这个表进行操作 * * * 创建一个虚拟表 * * 虚拟表可以设置字段 ,和对行的 增 删 改 查 * * 重点在于虚拟表的toString()方法; * * toString(); 方法能被TableRead 读取后,重建创建一个虚拟表 * * 这样,数据库的计设就变得简单了 一个字段可以是一个虚拟表的toString(); * 我们调用TableRead 对toString()进行增册改查 ,又将 TableRead转化成一个TableMake然后调用tableMak的toString()又存进了数据库 * * * * /** * 好友是多个的。而且未知数量 三部份 虚拟表的结构与作用 一虚拟表结构 这时我们有 几个选择 1 创建一张表专门储存好友 那么产生的结果, 1一个人为一个id便产生了 一个好友表 2多一个好友便多了一个表 3 一个id 还有同学,亲朋好友, ... 只要出现一个不是单项属性的,一个id 便产生了一个表。 一个id 有可能出现1或者更多张表。id多了,管理起来十分复杂麻烦 创建一条查询语句难度非常大,耗时长。 2 表结构化字符串:将一个字符串以表的形式进行增删改查字符串 这时,我们只需要有好友这个字符串属性就可以,不需要再创建一张表来储存好友, 因为好友的属性可以 做为表中的一行数据,存入了 表结构化的字符串。 获取时,我们只需要获取好友的属性进行字符串拆分便可以得到好友的数量和好友的其它属 性 每新增一个字段我们就进行字符串合成拆分。最后获得字符串以表型式进分的行为有 : 逻列表结构 表头: 姓名 年龄 好友 行: 小明 18 小苏,小强,小... 数据库创建表 :姓名 年龄 好友 好友的属性 1姓名 2联系方式 3性别 TableMake :结构 ,引用xml 标符制作的表头 <ts><t>姓名</t><t>好友</t><t>姓别</t></ts> <rs> <r><i>小强</i><i>13652336421</i><i>女</i></r> <r><i>小花</i><i>13652336421</i><i>男</i></r> </rs> 这时,我们将小明的好友属性 结构化就可以了,不需要再创建一张好友表来关联 创建这个结构有两种方式: 1 使用xml 2 使用 TableMake类 建议选择 TableMake 类 ; 因为他有特定的格式来保证 表结构的完整性 以下是TableMake 的示例 创建 TableMake 代码示例1 TableMake make= new TableMake("姓名","年龄","联系方式"); make.addRow("小苏",18,13580150692); //表中添加一行数据 ,添加一行时,一行数据的数量必需等于表头的数量,这一行储存失败 make.addRow("小强",19,13580150691); //表中添加 第二行数据 make.remove(1); //表中删除一行 make.up(1,new Object[]{"小苏","19","13555555"}); //修改一行时,如果这行数据不和对应表头的数量相等,修改失败 Object[] row = make.getRow(0); //表中获取一行 String table=make.toTable(); //将 make 打包成一个表格式的字符串 //假设有表: create table mytable( id int, name varchar(16), friend varchar default('<ts><t>好友</t>年龄<t></t><t>电话</t><t>姓别</t><t>备注</t></ts><rs>') ) 这样的设计缺点与优点 缺点: 每一个id 需要一个 friend为值的默认值,数据库的储存空间变小. 优点:1数据库只需要获取到 id的数据 就可以了,不需要再一次遍历另一张表才可以获取数据 优化:1我们可以将表头以代码 1 2 3 设置为字段 2调整表标签 二 关系型数据库简单地 操作虚拟表 Class.forName("jdbc:derby:Driver"); Connection conn=DriverMessage.getConnection("url",user,password); Statement stat=conn.createStatement(); // 程序中为表中的小明 id=1 添加一个好友 // 1先获得小明好友的字符串 //程序中添加一个id String sql="insert into mytable(id,name ) values(1,'小明')";// 因为是插入语句,所以这里只需要插入 id 和姓名两个值 //将小明添加到表中 stat.execUpdata(sql); sql="select friend from mytable where id=1,name = '小明'"; ResultSet set=stat.execQuery(sql); set.next(); String friend=set.getString("friend"); //创建虚拟表阅读 friend TableRead read=new TableRead(friend); //将阅读的数据转换成一个可操作的虚拟表 TableMake make=read.toTableMake(); //将小华添加到小明的好友中 make.addRow("小华",18,13580150692,"女","1995-12-12"); String friends=make.toTable();//将make再次转换为虚拟表 //更新小明的好友 String sql="update mytable set friend='"+ frends +"' where id=1,"+"name='小明'"; stat.execUpdata(sql); //此时,小明的好友中多了一个小华,表的结构依然完整,这时数据库已为小明添加了朋友小华, 我们不需要再将遍历小明的所有朋友 //这时我们查询虚拟表 小明的所有好朋友 如果没有更新数据,我们可以直接从make 中获取小明的所有好友 List<Object[]> friends=make.getRows(); Object[] xiaohuao=friends.get(0); System.out.print("姓名="+xiaohuao[0]+" 年龄="+xiaohuao[1]+" 电话="+xiaohuao[2]+" 姓别= "+xiaohuao[3]+" 生日="+xiaohuao[4]); //修改小明的朋友小华的手机号码 xiaohuao[2]=13580150692; friends=make.toTable(); //将make重新打包 String sql="update mytable set friend='"+ frends +"' where id=1,"+"name='小明'"; stat.execUpdate(sql); //这时我们发现,对小明的朋友们的操作只需要简单的操作一下make 而对数据库操作只需要 updata一条语句 关系型数据库中的使用 创建数据库插入语句 String sql= insert into tablename values("'"+"小明"+"',"+18+","'+ table + "'"); //关系型数据库中 省略了构建一张好友表的行为 三 非关系型数据库中的使用 JRides rides= new JReides("localhost"); rides.set("key",table); //代码示例2 DefaultTableModel model= new DefaultTableModel(new Object[][]{},new Object[]{}); TableMake make1= new TableMake(model); //代码示例3 Class.forName(DerbyURL.driver); Connection connection = DriverManager.getConnection( DerbyURL.dburl, DerbyURL.dbuser , DerbyURL.dbpassword ); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("select * from tablename"); TableMake make2=new TableMake( set ); 以上是TableMake 的一些操作 以下是分析TableMake 格式化过的字符串的TableRead 类将格式化过的字符串重组成 TableMake( String ) 类 String table = make.toTable(); TableRead read = new TableRead( table ); TableMake make4=read.toTableMake(); 1使用xml 读取 2使用 TableRead读取 * */ @SuppressWarnings("serial") public class TableMake implements Serializable{ private String[] types=null; private List<Object[]>rows=null; /**创建一个TableMake 并输入表中的字段*/ public TableMake(String... types) { this.types=types; rows=new LinkedList<>(); } public TableMake() { } @SuppressWarnings("rawtypes") public TableMake(DefaultTableModel model){ List<String> temptypes= new ArrayList<>(); for (int i = 0; i < model.getRowCount(); i++) { temptypes.add(model.getColumnName(i)); } types=temptypes.toArray(new String[] {}); Vector values=model.getDataVector(); rows = new LinkedList<>(); for (int i = 0; i < values.size(); i++) { Object[] row=((Vector)values.get(i)).toArray(); rows.add(row); } } /**设置表中的字段*/ public void setTypes(String... types) { this.types=types; } /** * 重置表 * */ public void reset(String[]types,LinkedList<Object[]>rows) { this.types=types; this.rows=rows; } /** * 如果添加一行length 不等于创建对象时的types的length * 如果添加一行的length 等于 types.length 添加成功返回true * 不添加并且返回false * */ public boolean addRow(Object... row) { if (row.length==types.length) { rows.add(row); return true; } return false; } public void removeRow(int i) { rows.remove(i); } public boolean upRow(int i,Object...row) { if (row.length==types.length) { rows.remove(i); rows.add(i,row); } return false; } public Object[] getRow(int i) { return rows.get(i); } public String toTable() { return toString(); } public String toString() { StringBuilder sb=new StringBuilder(); sb.append("<ts>"); for (int i = 0; i < types.length; i++) { sb.append("<t>"+types[i]+"</t>"); } sb.append("</ts>"); sb.append("<rs>"); for (int i = 0; i < rows.size(); i++) { sb.append("<r>"); Object[] row= rows.get(i); for (int j = 0; j < row.length; j++) { sb.append("<i>"+row[j]+"</i>"); } sb.append("</r>"); } sb.append("</rs>"); return sb.toString(); } /** * @return the rows */ public List<Object[]> getRows() { return rows; } /** * @param rows the rows to set */ public void setRows(List<Object[]> rows) { this.rows = rows; } /** * @return the types */ public String[] getTypes() { return types; } }
import index.s; /** * 读取 被TableMeke 结构化的 字符串 * 转化成一个TableMake * */ public class TableRead { /** * * */ String table=""; public TableRead(String table) { this.table=table; } public TableRead(TableMake tableMake) { table =tableMake.toString(); } public void readString(String table) { this.table=table; } public TableMake toTableMake() { TableMake make = new TableMake(getTypes()); make.setRows(getRows()); return make; } public String[] getTypes() { String typeArray=table.split("</ts>")[0].replace("<ts>",""); String[] types=typeArray.replace("<t>","").split("</t>"); return types; } public Object get(int r,int c){ return toTableModel().getValueAt(r, c); } public List<Object> getCoulmn(String type){ int index=-1; String[] types=getTypes(); for (int i = 0; i <types.length; i++) { if (type.equals(types[i])) { index=i; break; } } List<Object> re=new ArrayList<>(); DefaultTableModel modle=toTableModel(); for (int i = 0; i < modle.getRowCount(); i++) { re.add(modle.getValueAt(i, index)); } return re; } public List<Object> getCoulmn(int typeIndex){ List<Object> re=new ArrayList<>(); DefaultTableModel modle=toTableModel(); for (int i = 0; i < modle.getRowCount(); i++) { re.add(modle.getValueAt(i, typeIndex)); } return re; } /** * * */ public DefaultTableModel toTableModel() { DefaultTableModel model = new DefaultTableModel(new Object[][] {},getTypes()); if (model.getRowCount()>0) { model.removeRow(0); } String rowArray=table.replace("</rs>","").split("<rs>")[1]; String[] rows=rowArray.replace("<r>","").split("</r>"); for (int i = 0; i < rows.length; i++) { Object[] rowItem=rows[i].replace("<i>","").split("</i>"); for (int j = 0; j < rowItem.length; j++) { String item=rowItem[j].toString().trim(); if (s.isInteger(item)==true) { try { rowItem[j]=Integer.parseInt(item); } catch (Exception e) { } } else if (s.isLong(item)) { try { rowItem[i]=Long.parseLong(item); } catch (Exception e) { } } else if (s.isBoolean(item)==true) { rowItem[j]=Boolean.parseBoolean(item); } else if (s.isDouble(item)==true) { rowItem[j]=Double.parseDouble(item); } } model.addRow(rowItem); } return model; } public List<Object[]> getFirstRows(int rows){ return getRows().subList(0, rows); } public List<Object[]> getRows(int start,int end){ return getRows().subList(start, end); } public List<Object[]> getRows() { String rowArray=table.replace("</rs>","").split("<rs>")[1]; String[] rows=rowArray.replace("<r>","").split("</r>"); List<Object[]>re=new ArrayList<>(); for (int i = 0; i < rows.length; i++) { Object[] rowItem=rows[i].replace("<i>","").split("</i>"); for (int j = 0; j < rowItem.length; j++) { String item=rowItem[j].toString().trim(); if (s.isInteger(item)==true) { try { rowItem[j]=Integer.parseInt(item); } catch (Exception e) { } } else if (s.isLong(item)) { try { rowItem[i]=Long.parseLong(item); } catch (Exception e) { } } else if (s.isBoolean(item)==true) { rowItem[j]=Boolean.parseBoolean(item); } else if (s.isDouble(item)==true) { rowItem[j]=Double.parseDouble(item); } } re.add(rowItem); } return re; } }