如何在JTable中使用Resultset中的使用数据?

时间:2012-07-11 12:16:07

标签: java sql jtable resultset

我正在做一个学校项目,我遇到了将结果集中的数据存储在JTable中的问题。以前我使用过DButils,但现在我想知道是否有办法在不使用外部类文件或更容易使用DButils的情况下做同样的事情。

数据仅来自一个表,所有需要发生的事情是数据必须显示在JTable中。

我会在这里发布我的代码,但我已经查看了,我能找到的唯一教程是关于如何使用和Object [] []填充JTable的。我正在使用JDBC来创建连接。

提前致谢。

2 个答案:

答案 0 :(得分:1)

当然有一种方法:遍历ResultSet并将您找到的内容添加到传递给Object [][]的{​​{1}}数组中。在JTable中每行的2D数组中有一行;列是值。

你遇到的问题是你不会知道有多少行没有迭代它。这就是为什么将它加载到ResultSet可能是一个更好的主意。

这是一个展示如何操作的示例。你会在这个问题的答案中找到这种方法(以及更多):

java sql connections via class

Map<String, Object>

答案 1 :(得分:1)

这需要几个步骤。

我将解释我的方式,这对于非常大的集合是有益的,但是如果你只想显示几行则有点复杂。我仍然相信它会对你有所帮助。此方法将动态加载所需的记录,而不是整个装置。它创造了拥有整套装置的错觉,但不必等待长时间的装载。

1)好的,首先,让我们假设我们有一个很好的JFrame,你可以开始显示。所以首先我要添加一个JScrollPane,在里面我将添加一个JTable。运行它并确保你有一个漂亮的窗口,里面有一个空的JTable滚动条。

2)接下来你需要一个JTable的数据源。由于JTable是非专门用于SQL resultSets的非常通用的组件,因此它需要一个实现与SQL无关的javax.swing.table.AbstractTableModel的数据源。所以我们现在将创建一个将实现AbstractTableModel的TableModelClass,然后我们将它添加到JTable中,它将开始工作。当然,诀窍是实现所有使用我们的SQL结果集获取数据的AbstractTableModel方法,这取决于您。从这里是我的建议 - &gt;

3)由于这将是动态的,我们不需要预先加载所有数据,但我们需要一个初始设置来显示。我将有一个固定大小的Object [] [],比方说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

好的,希望有所帮助.--