毕设大部分功能已经完成,目前还在完善一些辅助功能,其中数据库管理就是一个重点,这一主要介绍通过Ext显示数据库的表。
一、服务器端的实现
由于之前已经有过实现的经验,因此服务器端的实现已经轻车熟路,下边先介绍这一块。
其实从面向对象的角度来说,特别是采用了SSH框架之后,我们可以直接通过hibernate获取对应表对象的集合,然后将集合发送至前台交给Ext处理。这样看起来挺不错,而且实际实现也不难,但是你仔细查看就会发现个很不爽的事情,每次发送的集合包含了大量的无用数据(甚至绝大多数的数据),为什么会这样呢?表关联的原因。hibernate生成的model会引入关联表的对象(或对象集合),而struts—json插件会将他们全部序列化,这在我们实际Ext的显示中不需要的。当然,你或许可以无视,但这绝对是个糟糕的设计,你将大量的网络流量耗费在了无效数据上。
那么怎么解决这个问题呢?有两个方法:一是通过struts—json提供的方法(一般用注解或result配置)指定这些数据不序列化,听着挺好,但做着费劲,你要么在model类中写入很多和这个类本身没有任何关系的注解,要么需要就在action的
既然这两种都不行,那么怎么处理呢?其实完全可以抛开hibernate,采用原始点的方法:先sql读取所有表名,然后根据表名读出字段名和对应数据,其中表数据使用二维数据存数即可,事实证明这种方法更灵活。
下边是实现代码:
1 /** 2 * 获取表名 3 * @return List<表明> 4 */ 5 public ListgetTables(){ 6 List mdbls=new ArrayList (); 7 Session se=HibernateSessionFactory.getSession(); 8 SQLQuery sq=se.createSQLQuery("show tables"); 9 List sls=sq.list(); 10 for(String str:sls){ 11 if("jbpm".equals(str.substring(0, 4))) 12 continue; 13 MyDataBase mdb=new MyDataBase(); 14 mdb.setTablename(str); 15 mdbls.add(mdb); 16 } 17 return mdbls; 18 } 19 20 /** 21 * 获取字段名 22 * @param tablename 表名 23 * @return 24 */ 25 public List getFields(String tablename){ 26 List mdbls=new ArrayList (); 27 Session se=HibernateSessionFactory.getSession(); 28 SQLQuery sq=se.createSQLQuery("desc "+tablename).addScalar("Field"); 29 List sls=sq.list(); 30 for(String str:sls){ 31 MyDataBase mdb=new MyDataBase(); 32 mdb.setFieldname(str); 33 mdbls.add(mdb); 34 } 35 return mdbls; 36 } 37 38 /** 39 * 获取字段 40 * @param tablename 表名 41 * @return 42 */ 43 public String[] getFieldsInArray(String tablename){ 44 String[] fields; 45 Session se=HibernateSessionFactory.getSession(); 46 SQLQuery sq=se.createSQLQuery("desc "+tablename).addScalar("Field"); 47 List sls=sq.list(); 48 fields=new String[sls.size()]; 49 for(int i=0;i ){ 50 fields[i]=sls.get(i); 51 } 52 return fields; 53 } 54 55 /** 56 * 获取表内容 57 * @param tablename 58 * @return 59 */ 60 public String[][] getTableContent(String tablename){ 61 String[][] content=null; 62 Session se=HibernateSessionFactory.getSession(); 63 SQLQuery sq=se.createSQLQuery("select * from "+tablename); 64 List
其中最终发送客户端的字段头格式如下:
"fieldheader":["{text:'rid',dataIndex:'rid',flex:1}","{text:'rname',dataIndex:'rname',flex:1}","{text:'rstring',dataIndex:'rstring',flex:1}"],"fields":["rid","rname","rstring"]
表数据格式如下:
"contentstr":["{'rid':'1','rname':'系统管理员','rstring':'admin'}","{'rid':'2','rname':'实训负责人','rstring':'manager'}","{'rid':'3','rname':'指导老师','rstring':'teacher'}","{'rid':'4','rname':'组长','rstring':'header'}","{'rid':'5','rname':'学生','rstring':'student'}"]
二、Extjs中grid的实现
其实实现动态grid的思路很简单,我们知道grid的表头是由columns属性指定的,而加载的数据是由对应的store决定的,想要让其动态改变,只需修改columns和store即可,而恰好Ext提供了reconfigure(Ext.data.Store store, Object[] columns)方法来实现这一操作。
Extjs里边首先需要一个combox下拉框,在打开grid的时候加载表名以供选择,其实现如下:
{ xtype: 'combobox', width: 219, id:'combtables', fieldLabel: '选择表', labelWidth: 50, maxWidth: 200, editable:false, valueField: 'tablename', displayField: 'tablename', store:Ext.create('sxpt.store.admin.Tables'), //对应store请求获取表名 labelWidth: 80 }
为实现动态的grid,我们首先要实现一个未指定store和空columns的grid,其实现代码如下:
1 Ext.define('sxpt.view.admin.DataBaseList',{ 2 extend: 'Ext.grid.Panel', 3 alias: 'widget.databaselist', 4 id:'databaselist', 5 title: '数据库管理', 6 region: 'center', 7 renderTo:Ext.getBody(), 8 columns:[], 9 bbar: { 10 xtype: 'pagingtoolbar', 11 id:'datapagebar', 12 displayInfo: true, 13 displayMsg: '显示 {0} - {1} 共 {2}条', 14 emptyMsg: "没有数据需要显示" 15 }, 16 dockedItems:[{ 17 dock: 'top', 18 xtype: 'toolbar', 19 layout:'fit', 20 items: [ 21 { 22 xtype:'tabpanel', 23 height:80, 24 items:[{ 25 xtype:'panel', 26 title:'查询表', 27 margin: '5 0 0 20', 28 items:[ 29 { 30 xtype: 'combobox', 31 width: 219, 32 id:'combtables', 33 fieldLabel: '选择表', 34 labelWidth: 50, 35 maxWidth: 200, 36 editable:false, 37 valueField: 'tablename', 38 displayField: 'tablename', 39 store:Ext.create('sxpt.store.admin.Tables'), 40 labelWidth: 80, 41 42 } 43 ] 44 } 45 ] 46 }] 47 });
之后为了每次选择表后就加载数据,在combobox中添加change监听器,实现如下:
1 listeners:{ 2 change:function(combo, record,index){ 3 var griddb=Ext.getCmp('databaselist'); 4 Ext.Ajax.request({ 5 url:'admin/admin_database_fieldsa', 6 params:{ 7 tablename:this.value 8 }, 9 method : 'POST', 10 success : function(response) { 11 var strT=response.responseText; 12 13 var json = Ext.JSON.decode(strT.replace(/\"\{/g,"{").replace(/\}\"/g,"}")); //替换掉由 于struts-json序列化产生的多余双引号 14 var store=Ext.create('Ext.data.Store',{ 15 fields:json.fields, 16 data:json.contentstr 17 }); 18 var pagebar=Ext.getCmp('datapagebar'); 19 pagebar.bind(store); //为分页栏加载数据 20 store.load(); 21 griddb.reconfigure(store,json.fieldheader); 22 }
至此,动态的grid就已经完成了。
三、一个问题
如果你注意struts—json插件的处理结果的话就会发现,它对String类型的属性序列化是会自动加上引号,如上边字段头格式序列化后为:
"fieldheader":["{text:'rid',dataIndex:'rid',flex:1}","{text:'rname',dataIndex:'rname',flex:1}","{text:'rstring',dataIndex:'rstring',flex:1}"]
但是我们期望的数据格式应该是不带红色引号的。这两者什么区别呢?主要是字符串执行Ext.JSON.decode()后的结果不一样,带引号的反序列化之后fieldheader是一个包含三个字符串的集合(这与服务器端一致,但却并非我们想要的),而不带引号的反序列化之后fieldheader里边包含的是3个对象,每个对象里边包含三个字段,这样的格式才是Extjs可以正确处理的json数据格式。
因此需要在反序列化之前对接收的字符串进行如下处理:
strT.replace(/\"\{/g,"{").replace(/\}\"/g,"}")
一下是完成的js代码:
1 Ext.define('sxpt.view.admin.DataBaseList',{ 2 extend: 'Ext.grid.Panel', 3 alias: 'widget.databaselist', 4 id:'databaselist', 5 title: '数据库管理', 6 region: 'center', 7 renderTo:Ext.getBody(), 8 //store: 'admin.Teacher', 9 columns:[], 10 bbar: { 11 xtype: 'pagingtoolbar', 12 id:'datapagebar', 13 displayInfo: true, 14 displayMsg: '显示 {0} - {1} 共 {2}条', 15 emptyMsg: "没有数据需要显示" 16 }, 17 dockedItems:[{ 18 dock: 'top', 19 xtype: 'toolbar', 20 layout:'fit', 21 items: [ 22 { 23 xtype:'tabpanel', 24 height:80, 25 items:[{ 26 xtype:'panel', 27 title:'查询表', 28 margin: '5 0 0 20', 29 items:[ 30 { 31 xtype: 'combobox', 32 width: 219, 33 id:'combtables', 34 fieldLabel: '选择表', 35 labelWidth: 50, 36 maxWidth: 200, 37 editable:false, 38 valueField: 'tablename', 39 displayField: 'tablename', 40 store:Ext.create('sxpt.store.admin.Tables'), 41 labelWidth: 80, 42 listeners:{ 43 change:function(combo, record,index){ 44 var griddb=Ext.getCmp('databaselist'); 45 Ext.Ajax.request({ 46 url:'admin/admin_database_fieldsa', 47 params:{ 48 tablename:this.value 49 }, 50 method : 'POST', 51 success : function(response) { 52 var strT=response.responseText; 53 54 var json = Ext.JSON.decode(strT.replace(/\"\{/g,"{").replace(/\}\"/g,"}")); 55 var store=Ext.create('Ext.data.Store',{ 56 fields:json.fields, 57 data:json.contentstr 58 }); 59 var pagebar=Ext.getCmp('datapagebar'); 60 pagebar.bind(store); 61 store.load(); 62 griddb.reconfigure(store,json.fieldheader); 63 } 64 }) 65 } 66 } 67 } 68 ] 69 } 70 } 71 ] 72 }], 73 initComponent: function () { 74 this.callParent(arguments); 75 } 76 });
源码暂时就不共享了,等过一段整理好了再发。