[摘錄]: http://www.itwen.com
在jdk1.4的javax.sql包中有一個RowSet接口,但是沒有具體實現(xiàn)的類。”Tiger”誕生之后,引入了 javax.sql.rowset包中的五個子接口和com.sun.rowset包里面的對應(yīng)的五個實現(xiàn)類,這樣我們就可是使用功能強(qiáng)大的RowSet 了。jdk1.5中RowSet的五個子接口分別是JdbcRowSet,CachedRowSet,WebRowSet,JoinRowSet和 FilteredRowSet,他們?yōu)槲覀兊臄?shù)據(jù)庫開發(fā)帶來了強(qiáng)大的功能和方便的操作。
我的java環(huán)境是:RedHat 9
Jdk 1.5.1_01
Eclipse 3.1m4
MySql 4.1.10 (JDBC Driver:org.gjt.mm.mysql.Driver)
我首先在test數(shù)據(jù)庫里面創(chuàng)建了兩個表用于這次的學(xué)習(xí),下面是腳本:
create table table1 (id int not null , name varchar(20) not null);
create table table2 (id int not null, info varchar(20) not null);
然后我就插入了一些數(shù)據(jù)用于測試。以下內(nèi)容以我的環(huán)境示意,大家只要修改相應(yīng)地方就可用于自己的測試。
RowSet 對象可分為兩類:有連接的和無連接的。JdbcRowSet是唯一一個有連接的實現(xiàn),和傳統(tǒng)的ResultSet一個樣,有連接的實現(xiàn)是基于Jdbc驅(qū)動的連接,數(shù)據(jù)庫的連接是貫穿整個對數(shù)據(jù)庫的操作。而無連接的實現(xiàn)是基于Reader和Writer流的連接,在需要讀取數(shù)據(jù)和寫入數(shù)據(jù)的時候才建立連接,在整個操作過程中都是斷開連接的,后面四個接口對象都是無連接的實現(xiàn)。下面我就針對每一個接口來介紹一下它們各自的功能。
JdbcRowSet接口:
我的理解是這個接口基本上和ResultSet有類似的功能,只不過它的結(jié)果集默認(rèn)是ResultSet.TYPE_SCROLL_INSENSITIVE和ResultSet.CONCUR_UPDATABLE的,也就是說默認(rèn)的結(jié)果集就是可以上下滾動和可更新的。
因為本身RowSet接口就是ResultSet的子接口,所以1.5里面的所有RowSet都有ResultSet的方法,而JdbcRowSet又只是在默認(rèn)的屬性和ResultSet有區(qū)別,所以它對結(jié)果集的操作方法和ResultSet都是一樣的,我就不具體介紹了,大家可以參考API。
下面我介紹一下JdbcRowSet的創(chuàng)建方法,這有兩種方法,一種是基于傳統(tǒng)的JDBC連接數(shù)據(jù)庫的方法:
1
Class.forName(“org.gjt.mm.mysql.Driver”);
2
Connection conn=DriverManager.getConnection(“jdbc:mydql://localhost:3306/test”,”root’,””);
3
Statement stmt=conn.createStatement();
4
ResultSet rs=stamt.executeQuery(“select * from table1”);
5
JdbcRowSet jrs=new JdbcRowSetImpl(rs);
這樣就創(chuàng)建了一個對象(JdbcRowSetImpl是com.sun.rowset包里面的實現(xiàn)類,文中的五個接口在包中都對應(yīng)有一個實現(xiàn)類),這個對象里面的數(shù)據(jù)就是和rs里面的數(shù)據(jù)是一樣的。還有一種創(chuàng)建的方法是使用默認(rèn)的構(gòu)造方法,然后set屬性得到數(shù)據(jù),個人推薦使用第二種方法:
1
JdbcRowSet jrs=new JdbcRowSetImpl();
2
jrs.setUrl(“jdbc:mydql://localhost:3306/test”);
3
jrs.setUsername(“root”);
4
jrs.setPassword(“”);
5
jrs.setCommand(“select * from table1”);
6
jrs.execute();
這樣創(chuàng)建的對象是和第一種方法是一樣的結(jié)果。當(dāng)然這種方法可以連接一個數(shù)據(jù)源,如果我們在上下文環(huán)境種綁定了一個數(shù)據(jù)源,JNDI名字是dataSource1,那么下面的代碼就可以獲得對象:
1
JdbcRowSet jrs=new JdbcRowSetImpl();
2
jrs.setDataSourceName(“dataSource1”)
3
jrs.execute();
得到對象之后我們就可以使用相應(yīng)的方法來對數(shù)據(jù)進(jìn)行遍歷,更新,插入或者刪除。
我有2點(diǎn)要說明:第一,其它四個接口的對象中除了JoinRowSet創(chuàng)建方式基本都是一樣的,只是接口名字和接口實現(xiàn)類的名字不同而已,后面我就不再說明創(chuàng)建對象的方法了。第二,雖然JdbcRowSet默認(rèn)是可滾動和可更新的,但是這也是需要數(shù)據(jù)庫驅(qū)動支持的,我使用的MySql驅(qū)動就不支持更新結(jié)果集,所以大家使用之前需要閱讀驅(qū)動的說明文檔。
CachedRowSet接口:
它繼承于RowSet接口,而且他是無連接的RowSet的其他3個實現(xiàn)的父接口,也就是說其他3個接口都直接或者間接繼承了它。從名字我們可以知道,它的原理就是讀入數(shù)據(jù)保存在緩存進(jìn)行相應(yīng)的操作。
創(chuàng)建接口對象除了上面的兩種創(chuàng)建方式,還有一個方法,就是在構(gòu)造方法里面?zhèn)鬟f一個SyncProvider。之前我說過無連接的RowSet都是基于流讀寫的,那么這里所說的SyncProvider就是提供了特定的Reader和Writer。jdk1.5文檔的Sample Coder有這樣的實現(xiàn):
1
String provider= “com.fred.providers.HighAvailabilityProvider”
2
CachedRowSet crs=new CachedRowSetImpl(provider);
這樣我們就為RowSet設(shè)置了特定的Reader和Writer,但是這是需要第三方的包支持的。而我們使用無參的構(gòu)造方法創(chuàng)建的對象是使用了默認(rèn)的 SyncProvider,當(dāng)然一般來說這對于我們就已經(jīng)足夠了。創(chuàng)建了對象之后就可以使用和JdbcRowSet一樣的方法來進(jìn)行就結(jié)果集的增刪改操作了,但是唯一不同的就是在更新了結(jié)果集之后必須調(diào)用Writer將緩存中的數(shù)據(jù)寫入數(shù)據(jù)庫,而其方法就是crs.acceptChages();
CachedRowSet提供的最令人興奮的功能就是分頁功能。以前程序員很頭疼的問題就是怎么處理數(shù)據(jù)分頁而不影響性能,現(xiàn)在有了CachedRowSet一切都變得那么簡單,請看下面的代碼:
1
CachedRowSet crs=new CaehedRowSetImpl();
2
crs.setUrl(“jdbc:mydql://localhost:3306/test”);
3
crs.setUsername(“root”);
4
crs.setPassword(“”);
5
crs.setCommand(“select * from table1”);
6
crs.setPageSize(5);
7
crs.execute();
8
while(crs.nextPage())
9
while(crs.next())
10
System.out.println(crs.getInt(“id”+”\t\t”+crs.getString(“name”));
我們在crs.execute()之前設(shè)置每頁的數(shù)據(jù)行數(shù),那么Reader讀取數(shù)據(jù)的時候就只讀指定的行數(shù)的數(shù)據(jù),這樣我們就避免了一次讀取所有數(shù)據(jù)再進(jìn)行分頁操作。是不是很簡單呢?
JoinRowSet接口:
這個接口可以提供我們在無連接的狀態(tài)下直接對結(jié)果集進(jìn)行Join。下面的代碼提供了JoinRowSet的實現(xiàn):
1
CachedRowSet crs1=new CaehedRowSetImpl();
2
crs1.setUrl(“jdbc:mydql://localhost:3306/test”);
3
crs1.setUsername(“root”);
4
crs1.setPassword(“”);
5
crs1.setCommand(“select * from table1”);
6
crs1.execute();
7
CachedRowSet crs2=new CaehedRowSetImpl();
8
crs2.setUrl(“jdbc:mydql://localhost:3306/test”);
9
crs2.setUsername(“root”);
10
crs2.setPassword(“”);
11
crs2.setCommand(“select * from table2”);
12
crs2.execute();
13
JoinRowSet jrs=new JoinRowSetImpl();
14
jrs.addRowSet(crs1,”id”);
15
jrs.addRowSet(crs2,”id”);
16
while(jrs.next())
17
System.out.println(jrs.getInt(“id”)+”\t\t”+jrs.getString(“name”)+”\t\t”+jrs.getString(“info”);
這段代碼的作用和執(zhí)行select * from table1 inner join table2 on table1.id=table2.id語句得到的結(jié)果集是一樣的。但是我個人認(rèn)為與其這樣復(fù)雜地使用JoinRowSet,不如直接使用這條Join語句來得到CachedRowSet。
默認(rèn)的Join是inner join的,接口還支持cross join,full join,left outer join和right outer join,我們通過setJoinType()方法來修改連接類型,當(dāng)然這還是需要數(shù)據(jù)庫的支持。還有一個值得注意的地方就是,在這個例子里我連接的列在兩個表里面都叫id,那么我們?nèi)?shù)據(jù)的時候就使用id這個名字,那如果兩列的名字不一樣呢?系統(tǒng)就會為這個連接列取一個默認(rèn)的名字叫做” MergedCol”。
FilteredRowSet接口:
.NET的ADO.NET支持獲取結(jié)果集使用一定的條件過濾從而得到不同的結(jié)果,那現(xiàn)在jdk1.5也能做到了,F(xiàn)ilterRowSet接口讓我們可以靈活地定義過濾條件達(dá)到不同的效果。Javax.sql.rowset包里面的Predicate接口就是這個過濾器,我們通過實現(xiàn)這個接口定義過濾條件,下面是示意代碼:
1
public class Filter implements Predicate
{
2
private int min;
3
private int max;
4
private String colName;
5
public Filter (int min ,int max ,String colName)
{
6
this.min=min; this.max=max; this.colName=colName;
7
}
8
public boolean evaluate (RowSet rs)
{
9
CachedRowSet crs=(CachedRowSet)rs;
10
if((crs.getInt(colName)>min)&& (crs.getInt(colName)
{
11

12
}
13
}
14
}
15
posted on 2006-03-02 23:46
kelven 閱讀(212)
評論(0) 編輯 收藏 所屬分類:
java