2012-07-11 44 views
0

我正在做一個學校項目,我無法將結果集中的數據存儲在JTable中。以前我用過DButils,但現在我想知道是否有辦法做同樣的事情,而不必使用外部類文件,或者如果它更容易使用DButils。如何使用JTable中Resultset的使用數據?

數據僅來自一個表,所有需要發生的數據都必須顯示在JTable中。

我會在這裏發佈我的代碼,但我看了,我能找到的唯一教程是關於如何使用和Object [] []填充JTable的教程。我正在使用JDBC來創建連接。

在此先感謝。

+0

你可以作爲樣品使用:http://technojeeves.com/joomla/index.php/free/59-resultset-to-tablemodel – 2012-07-11 12:21:06

回答

1

當然有一種方法:遍歷ResultSet並將您發現的內容添加到傳遞到JTableObject [][]數組中。對於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; 
} 
+0

你可以給我一個代碼示例或簡單的英語解釋嗎? (我真的不明白) – AceFire6 2012-07-11 19:38:06

+0

如何遍歷'ResultSet'的例子已經廣泛使用。這[示例](http://stackoverflow.com/a/9134371/230513)顯示瞭如何在'Map'周圍創建'TableModel'。 – trashgod 2012-07-12 18:23:11

1

嗯,這將需要幾個步驟。

我會解釋一下我的方式,這對於很大的套件很有用,但是如果您只想顯示幾行,則會有點複雜。不過,我相信它會幫助你。這種方法將在飛行中加載所需的記錄,而不是全部加載。它創造了整套的幻覺,但無需等待長時間的負載。

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

好,希望幫助.--

+0

對'AbstractTableModel'+1,也顯示[這裏](http://stackoverflow.com/a/9134371/230513)。你可以使用更窄的'fireXxx()'方法。 – trashgod 2012-07-12 18:27:06

相關問題