问题的提出:
一般情况下,我们采用分页技术来解决大数据量加载的问题,这也是最好的办法。但是在有的项目中会遇到一次加载"万单位级别"数据的需求。尽管这是很糟糕的做法,即耗资源、加载速度又慢,但用户明指明了这样的需求,不这么做还不行。
解决方法:
采用
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
{
//
因为条目都是直接创建的,这样初始化的过程就相当慢
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)