我正在做一個學校項目,我無法將結果集中的數據存儲在JTable中。以前我用過DButils,但現在我想知道是否有辦法做同樣的事情,而不必使用外部類文件,或者如果它更容易使用DButils。如何使用JTable中Resultset的使用數據?
數據僅來自一個表,所有需要發生的數據都必須顯示在JTable中。
我會在這裏發佈我的代碼,但我看了,我能找到的唯一教程是關於如何使用和Object [] []填充JTable的教程。我正在使用JDBC來創建連接。
在此先感謝。
我正在做一個學校項目,我無法將結果集中的數據存儲在JTable中。以前我用過DButils,但現在我想知道是否有辦法做同樣的事情,而不必使用外部類文件,或者如果它更容易使用DButils。如何使用JTable中Resultset的使用數據?
數據僅來自一個表,所有需要發生的數據都必須顯示在JTable中。
我會在這裏發佈我的代碼,但我看了,我能找到的唯一教程是關於如何使用和Object [] []填充JTable的教程。我正在使用JDBC來創建連接。
在此先感謝。
當然有一種方法:遍歷ResultSet
並將您發現的內容添加到傳遞到JTable
的Object [][]
數組中。對於ResultSet
中的每一行,二維數組中有一行;列是值。
你會遇到的問題是,你不知道有多少行沒有迭代就回來了。這就是爲什麼將它加載到Map<String, Object>
可能是一個更好的主意。
下面是顯示如何操作的示例。你會發現在我回答這個方法(及以上)對這個問題:
java sql connections via class
public static List<Map<String, Object>> map(ResultSet rs) throws SQLException {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
try {
if (rs != null) {
ResultSetMetaData meta = rs.getMetaData();
int numColumns = meta.getColumnCount();
while (rs.next()) {
Map<String, Object> row = new HashMap<String, Object>();
for (int i = 1; i <= numColumns; ++i) {
String name = meta.getColumnName(i);
Object value = rs.getObject(i);
row.put(name, value);
}
results.add(row);
}
}
} finally {
close(rs);
}
return results;
}
嗯,這將需要幾個步驟。
我會解釋一下我的方式,這對於很大的套件很有用,但是如果您只想顯示幾行,則會有點複雜。不過,我相信它會幫助你。這種方法將在飛行中加載所需的記錄,而不是全部加載。它創造了整套的幻覺,但無需等待長時間的負載。
1)好吧,首先,讓我們假設我們有一個很好的JFrame,您可以顯示,首先。所以首先我將添加一個JScrollPane,並在其中添加一個JTable。運行它,並確保在滾動條內部有一個空JTable的好窗口。
2)所以接下來你需要一個JTable的數據源。由於JTable是一個非專用於SQL resultSets的通用組件,因此它需要一個實現javax.swing.table.AbstractTableModel的數據源,該數據源與SQL無關。所以我們現在創建一個TableModelClass來實現AbstractTableModel,然後我們將這個添加到JTable中,它將開始工作。當然,訣竅是通過使用我們的SQL結果集來實現所有的AbstractTableModel方法來獲取數據,這取決於您。從這裏我的建議 - >
3)由於這是動態的,我們不需要加載所有的數據,但我們需要一個初始設置來顯示。我會有一個固定大小的對象[] [],可以說200 - 300行。所以我將首先執行SQL並填充200-300行緩衝區大小的數組。要緩存多少取決於兩件事情:1它應該足以獲得JTable當前顯示大小的所有數據,並且2應該足夠小,以便當我們滾動並獲得後續緩存時,它將非常快速地執行。
4)現在讓我們開始實現所有AbstractTableModel的接口方法。
5)首先我們看一下初始結果集並報告列數。只需添加一個類變量,設置列數並使用它返回:public int getColumnCount()。這從現在起不會改變。
6)還要查看結果集元數據,在類中創建一個列表變量並添加元數據中返回的列名稱。使用此列表將返回「getColumnName(int col)」中的列名稱。當然,col索引是結果集中的列位置。
7)現在讓我們做「int getRowCount()」。在TableModelClass中保留一個變量來包含rowCount,並以此方法返回它。提示:現在不要擔心,將其設置爲65000這樣的固定大數字,這會讓您在動態加載記錄時進行滾動。一旦我們達到最後,我們會將數字設置爲真實值,滾動窗格將調整到正確的比例。相信我,它工作正常。
8)現在來了有趣的一部分。由於JTable呈現表格的第一個「頁面」,並且在用戶滾動時它將開始調用「getValueAt(int row,int col)」。這將直接映射到我們的Object [] [],但由於我們只有一個緩存,而不是整個表,所以當用戶向下滾動時,我們需要獲取更多數據。我這樣做:
public Object getValueAt(int row, int col)
{
// load failed before, no more trying...
if(loadExceptionOccur || (row >= visualTableSize)) return("");
// check if requested row is OUT of cache …
try{
if(
// less than cache lower limit...
((row < startRow)
||
// Beyond cache upper limit...
(row >= startRow + tableDataCache.size()))
// Stop unnecessary loading, because of Jtable readjusting
// its visual table size and redrawing the entire table.
&& !tableRedraw
// yes, get new cache...
){
load(row); // <- below is code
}
// now we now the row is in cache, so ->
// verify requested cell in cache, or beyond data rows,
if(
// greater than lower limit
(row >= startRow)
&&
// less than upper limit...
(row < (startRow + tableDataCache.size()))
){
tableRedraw = false;
// just get the data from the cache. tableDataCache is just your Object[][] array…
Object cellValue = ((recordClass) tableDataCache.get(row-startRow)).getValueAt(col);
return (cellValue);
}
else{
// just show as blank
return("");
}
}
catch(Exception error ){
…
如果緩存未命中,您需要重新加載緩存數據。我通常會在請求行之前加載一些行,並且至少在一個JTable頁面大小之前加載一些行,這樣我們只需要一次到db來渲染一個屏幕。加載之前,緩存越大,滾動越多,但加載緩存所用的時間越長。如果您調整它,緩存處理可能幾乎不明顯。
這裏是「負載」的實現:
public void load(int rowIndex)
throws KExceptionClass
{
// calculate start of new cache, if not enough rows for top half of cache
// then start from 0
int halfCache = cacheSize/2 ;
int DBStartRow = 0;
if(rowIndex > halfCache) DBStartRow = rowIndex - halfCache;
//Do query to DB
try{
SQLP.load(DBStartRow, cacheSize); // <- using jdbc load from DbsartRow as many rows as cacheSize. Some sample SQL paging code below ->
}catch(Exception loadError){
// if the database fails or something do this, so you don’t get a billion errors for each cell. ->
//set load failed flag, kill window
loadExceptionOccur = true;
visualTableSize = 0;
tableDataCache = new ArrayList<recordClass>();
fireTableDataChanged(); // clear the Jtable
// log error
log.log(this, KMetaUtilsClass.getStackTrace(loadError));
// show error message
throw new KExceptionClass("Could not load table data! " , loadError);
}
//Load rows into the cache list.
//Key field values are in the cache list as the last field in each record.
tableDataCache.clear(); // the Object [][], wrapped in class
while(SQLPreprocessor.nextRowValue()) {
SQL.fetch(record); //<- get JDBC rows to table cache
tableDataCache.add(record); // this uses my library, change to JDBC or what ever you use to access SQL
}
log.log(this, "cacheList size = " + tableDataCache.size());
//---------
if(
// Last requested row number
(DBStartRow + cacheSize) >
// Last replied row number
(SQLPreprocessor.getloadedStartRowIndex() + SQLPreprocessor.getloadedRowCount())
){
// It is the end of table.
// The visual table is readjusted accordingly.
visualTableSize = SQLPreprocessor.getloadedStartRowIndex() + SQLPreprocessor.getloadedRowCount();
fireTableDataChanged();
tableRedraw = true;
}
startRow = SQLPreprocessor.getloadedStartRowIndex();
log.log(this, "visualTableSize = " + visualTableSize);
}
確定這將動態地加載在小高速緩存中的數據,這將得到具有整套的印象。 如果用戶滾動到中間或一直到最後,JTable將只詢問數據需要在移動時不顯示所有行,因此,如果您有一個10K的行表,但JTable只是20行高,滾動到結束將只需要40-50行加載。很不錯。您的用戶會留下深刻的印象。
現在的事情是,負載假定您有一個SQL遊標,它按行號向前和向後移動。這個簡單的事情在SQL中是一個相當大的挑戰。對於Oracle檢查:http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html
好,希望幫助.--
對'AbstractTableModel'+1,也顯示[這裏](http://stackoverflow.com/a/9134371/230513)。你可以使用更窄的'fireXxx()'方法。 – trashgod 2012-07-12 18:27:06
你可以作爲樣品使用:http://technojeeves.com/joomla/index.php/free/59-resultset-to-tablemodel – 2012-07-11 12:21:06