用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.73GHz512M內存,

用的是:jdk1.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)
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章