用SWT中的虚拟表格解决大数据量加载问题

问题的提出: 一般情况下,我们采用分页技术来解决大数据量加载的问题,这也是最好的办法。但是在有的项目中会遇到一次加载"万单位级别"数据的需求。尽管这是很糟糕的做法,即耗资源、加载速度又慢,但用户明指明了这样的需求,不这么做还不行。
 
解决方法: 采用 SWT 中的虚拟表格技术来创建拥有大数据量的表格,解决加载速度让人难以忍受的问题,提升加载效率。
         为了充分的说明问题,本文通过对比常规方法和虚拟表格技术加载 2 万条数据所需的时间,来说明虚拟表格在加载大数据量时的优越表现。
 
第一步:准备数据
1.  首先建立所需的数据表
 
create table user (id int(10) primary key auto_increment, name1 varchar(20) , name2 varchar(20) , name3 varchar(20) , name4 varchar(20)) type=innodb;
 
2. 插入数据 (写测试的目的一般带有破坏性,我插了 2 万条)
 
  for ( int i=0;i<20000;i++)
            {
            String s = "chengang" ;
            sm.executeUpdate( "insert into test_table (name0,name1,name2,name3) values ('" + s+1 +i + "','" + s +2+i + "','" + s +3+i + "','" + s +4+i + "')" );
            }
 
3 .创建一个 DAO 文件,用来处理插入和获得数据:
 
ConnDAO.java,详细内容请参看源文件
// 按照给定的 sql 进行数据库查询
// 取出数据后,赋值个 Vector ,并返回
  public Vector executeQuery(String sql)
 {
    ResultSet rs = null;
    Vector vResult = new Vector();
    try
   {
        Class.forName(driver);
        con = DriverManager.getConnection(dburl,userName,password);
        stmt = con.createStatement();
        rs = stmt.executeQuery(sql);
        ResultSetMetaData rsmd = rs.getMetaData();
        int  numCols = rsmd.getColumnCount();
         while (rs.next())
              {
                     String strTempArray[] = new String[numCols];
          for(int i = 1; i <= numCols; i++)
                     {
                  /* 将存储过程得到的每个字段赋值到字符串数组,并将其做为对象加入到 vector 类中返回 */
            strTempArray[i - 1] = rs.getString(i);
                     }
                     vResult.addElement(strTempArray);
              }
       
    }catch(Exception e)
    {
        System.out.println("Query Error!!!!!!!!!");
    }
    return vResult;
  }
}
 
第二步:创建测试文件
 
在开始之前,请你确认正确安装了 SWT Designer ,创建一个基于 SWT/JFS 的项目(不是必须,但这样可以方便使用可视化编辑,当然你也可以直接编写代码)。
 
 1 .为了与虚拟表格进行对比,我们首先用普通 Table 加载这 2 万条数据。
 
HelloWorld_Common.java
package edu.bjtu.zhao.demo;
//import 引入相关的类,具体可以参考本文的源文件
 
public class HelloWorld_Common {
 
       private static Table table;
       /**
        * Launch the application
        * @param args
        */
       public static void main(String[] args) {
      
       // 为了清晰说明问题,在此省略了相关部分代码,可以参考 源代码
              table = new Table(shell, SWT.BORDER);// 注意此处与虚拟表格设置的不同
             
              table.setBounds(40, 30, 723, 290);
             
// 此处省略了创建 5 列的代码,
              try  
              {  
//                   获得数据表格数据
                       ConnDAO dao = new ConnDAO();
                       String ss= "select * from test_table";//SendTable 为表名
                      final Vector  vResult = dao.executeQuery(ss);
                      for (int i=0;i<vResult.size();i++)
                      {
                           // 因为条目都是直接创建的,这样初始化的过程就相当慢
TableItem  item = new TableItem(table,SWT.NONE);   
                             item.setText((String[])vResult.get(i)); 
                      }
              }catch(Exception exception)  
              {  
                  exception.printStackTrace();  
              }
       }
}
 
   写完程序后,你可以直接在 Eclipse 中运行,运行结果如下图所示,当然不要忘记适当的计算一下时间 , 我的电脑的配置是:
Intel 双核 1.73GHz 512M 内存,
用的是: jdk 1.5.0 _06   MySQLversion: 4.0.14-nt
我的运行时间约是: 10 秒。
我想这样的速度,你的客户是不能忍受的,而且创建了那么多的 Item ,如果用户不看,且不是造成了严重的资源浪费。
 
2 .做了这么多准备工作,下面开始令人兴奋的虚拟表格之旅吧。
 
创建 HelloWorld_Virtual.java
package edu.bjtu.zhao.demo;
 
//import ……具体的包,可以参见附件中的源代码
 
public class HelloWorld_Virtual {
 
       private static Table table;
      
       /**
        * Launch the application
        * @param args
        */
       public static void main(String[] args) {
              //final Vector vResult = new Vector();
              final Display display = Display.getDefault();
             
              final Shell shell = new Shell();//shell 是主程序窗口
             
              shell.setSize(808, 375);// 设置窗体初始化大小
              shell.setText("SWT Application");// 设置窗体名称
              shell.open();// 主程序打开
///////////////////////// 创建表格 //////////////////////////////////
              table = new Table(shell, SWT.BORDER| SWT.VIRTUAL);// 注意此处的设置
              table.setLinesVisible(true);
              table.setHeaderVisible(true);
              table.setBounds(40, 30, 723, 290);
/////////////////// 创建表格四列 ////////////////////////////////////////////
              final TableColumn newColumnTableColumn = new TableColumn(table, SWT.NONE);
              newColumnTableColumn.setWidth(100);
              newColumnTableColumn.setText("id");
             
       /// 同样的方法创建另外 4
             
////////////////////////////////////////////////////////////////////////////////////////////////////
             
           // 获得数据表格数据
                ConnDAO dao = new ConnDAO();
                String ss= "select * from test_table";//SendTable 为表名
               final Vector  vResult = dao.executeQuery(ss);
               
              ///////////// 设置监听 /////////////////////////////////
               
              /* table.addListener(SWT.SetData, new Listener() { 
                   public void handleEvent(Event event) { 
                      TableItem item = (TableItem)event.item; 
                      int index = event.index; 
                      item.setText((String[])vResult.get(index)); 
                   }    
               });  */
        ////////////// 另一种方式实现虚拟表格 ///////////////////////////////////
         final int PAGE_SIZE = 100; 
             table.addListener (SWT.SetData, new Listener () {
                 public void handleEvent (Event event) {
                     TableItem item = (TableItem) event.item;
                     int index = event.index;
                     int page = index / PAGE_SIZE;
                     int start = page * PAGE_SIZE;
                     int end = start + PAGE_SIZE;
                     end = Math.min (end, table.getItemCount ());
                     for (int i = start; i < end; i++) {
                        item = table.getItem (i);
                       item.setText ((String[])vResult.get(i));
             }
                 }
              });
           ////////////// 设计总记录数,便于滚动条计算 //////////////////////////////////////////////////      
              table.setItemCount(vResult.size()); 
 
              shell.layout();// 主程序布置
              while (!shell.isDisposed()) {// 如果主程序没有关闭,这一直循环
                     if (!display.readAndDispatch())// 如果不忙
                            display.sleep();// 休眠
              }
       }
}
 
   呵呵, run 一下吧,我测试的结果,算上绘制界面的时间也就 1 秒左右, 如果在界面上做个查询,再来显示的话,基本“万单位”级别的数据也能做到即时加载啦

    在源代码中我已经做了较详细的注释,因为本文主要以实际操作为主,所以没有对具体的方法进行深入的分析。另外一个原因就是,现在网上有一篇文章《Virtual Tables and Trees》对虚拟表格和树做了较深入的分析,我不再重复他人的劳动,你可以参考一下。网上有这篇文章的中文版,不过如果你打算在IT界混的话,还是建议你读英文吧。

 
参考文献 Virtual Tables and Trees  June 2006  by Beatriz Iaderoza (IBM Ottawa Lab) and Grant Gayed (IBM)
 

本文出自 “Grow up” 博客,转载请与作者联系!

你可能感兴趣的:(大数据量,职场,SWT,休闲,虚拟表格)