問題的提出:一般情況下,我們採用分頁技術來解決大數據量加載的問題,這也是最好的辦法。但是在有的項目中會遇到一次加載"萬單位級別"數據的需求。儘管這是很糟糕的做法,即耗資源、加載速度又慢,但用戶明指明瞭這樣的需求,不這麼做還不行。
解決方法:採用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 內存,
用的是: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界混的話,還是建議你讀英文吧。