亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Hacking swing: 一個JDBC表控件模型

2019-11-18 12:37:53
字體:
來源:轉載
供稿:網友

簡單快速的將數據庫中的表引入Swing之內

  假如你已經用過數據庫了,你很可能已經用過為數據庫提供的維護和查詢表的工具:命令行工具很適合作簡單而直接的工作,但是很難完成大量數據的處理工作。在一次查詢中寫一條返回10或20列的數據就已經很困難了-更糟的是由于換行而使每條記錄都有很多行的情況,此時你根本無法區分一條記錄在哪一行結束,另一條記錄在哪一行開始。
  假如能夠將數據庫中表的內容映射到Swing的JTable中是否好一些呢?加上一些JDBC語句,添加到JFrame上,頃刻之間就形成了圖形界面。

建立連接

  假如你同時用到JDBC和Swing,只需要一句話你就可以抓住要點:使用數據庫表的元數據來建立Swing表控件模型。假如你還沒用到它們,下面就是你需要了解的背景知識:JDBC提供許多抽象方法來存取數據庫。對于一個數據庫有效的java代碼也應該對其他數據庫有效,唯一的不同之處在于JDBC與不同的數據庫建立連接時所需要提供的下面的一些字符串也是不同的:
¨        一個驅動程序類的類名,提供各種不同的java.sql接口的實現。
¨        一個連接到數據庫的URL。這就意味著可能會用到socket,盡管這不是一定的。一些小的可嵌入的數據庫就像你的應用程序一樣可以存活于Java虛擬機中。
¨        一個可選的用戶名。
¨        一個可選的密碼。

  一旦建立了連接,你就可以發送一些命令(創建、刪除、或修改表),或者通過該連接,創建SQL語句來對數據庫進行查詢。你也能通過該連接得到數據庫的元數據,例如它所支持的各種特性,某一字符串的最大長度等等。更重要的是,它可以讓你知道數據庫中都有哪些表,它們都有哪些字段,每個字段的數據類型是什么。

  因此,假設連接到了數據庫,并且知道該數據庫中的一個表的表名,你就可以利用兩次查詢將表的內容用Java表現出來。第一次查詢能得到該表的各字段的元數據并且將字段名和字段的類型構建成一個數組。這些能被適當地而且很好地映射到Java類中,至少支持你想支持的各種類型。第二次查詢得到表中所有的數據。對于每行數據,對應字段它都有相應的值。這些數據可以放入一個二維數組中,該數組存放的是整個表的內容。

  通過這兩次查詢,也就完成了要實現AbstractTableModel類中的抽象方法的所有預備:
¨        getRowCount():是你所創建的內容數組contents的長度。
¨        getColumnCount():假如沒有內容則為0,否則為數組contents的第一項(該項也是一個數組,因為內容數組是一個二維數組)的長度。
¨        getValueAt():contents[row][col]的值。

  AbstractTableModel已經完全的實現了getColumnClass()和getColumnName()兩個方法,因此,前者總是返回Object.class,后者返回"A","B","C",等等;你也可以利用第一次查詢的字段元數據覆蓋這兩個方法,以更好的實現它們。
例3-12演示JDBCTableModel如何被實現。

例3-12.由數據庫連接生成的Swing表控件模型

        import javax.swing.*;
        import javax.swing.table.*;
        import java.sql.*;
        import java.util.*;
        /** an immutable table model built from getting
                metadata about a table in a jdbc database
        */
        public class JDBCTableModel extends AbstractTableModel {
                Object[][] contents;
                String[] columnNames;
                Class[] columnClasses;

                public JDBCTableModel (Connection conn, String tableName)
                        throws SQLException {
                        super();
                        getTableContents (conn, tableName);
                }
                PRotected void getTableContents (Connection conn,
                                         String tableName)
                        throws SQLException {

                // get metadata: what columns exist and what
                // types (classes) are they?
                DatabaseMetaData meta = conn.getMetaData();
                System.out.println ("got meta = " + meta);
                ResultSet results =
                        meta.getColumns (null, null, tableName, null);
                System.out.println ("got column results");
                ArrayList colNamesList = new ArrayList();
                ArrayList colClassesList = new ArrayList();
                while (results.next()) {
                        colNamesList.add (results.getString ("COLUMN_NAME"));
                        System.out.println ("name: " +
                                results.getString ("COLUMN_NAME"));
                        int dBType = results.getInt ("DATA_TYPE");
                        switch (dbType) {
                        case Types.INTEGER:
                colClassesList.add (Integer.class); break;
                        case Types.FLOAT:
                colClassesList.add (Float.class); break;
                        case Types.DOUBLE:
                        case Types.REAL:
                colClassesList.add (Double.class); break;
                        case Types.DATE:
                        case Types.TIME:
                        case Types.TIMESTAMP:
                colClassesList.add (java.sql.Date.class); break;
                        default:
                colClassesList.add (String.class); break;
                        };
                        System.out.println ("type: " +
                                results.getInt ("DATA_TYPE"));
                        }
                        columnNames = new String [colNamesList.size()];
                        colNamesList.toArray (columnNames);
                        columnClasses = new Class [colClassesList.size()];
                        colClassesList.toArray (columnClasses);
                        
                        // get all data from table and put into
                        // contents array

                        Statement statement =
                conn.createStatement ();
                        results = statement.executeQuery ("SELECT * FROM " +
                                                  tableName);
                        ArrayList rowList = new ArrayList();
                        while (results.next()) {
                ArrayList cellList = new ArrayList();
                for (int i = 0; i<columnClasses.length; i++) {
                        Object cellValue = null;


                        if (columnClasses[i] == String.class)
                cellValue = results.getString (columnNames[i]);
                        else if (columnClasses[i] == Integer.class)
                cellValue = new Integer (
                                results.getInt (columnNames[i]));
                        else if (columnClasses[i] == Float.class)
                cellValue = new Float (
                                results.getInt (columnNames[i]));
                        else if (columnClasses[i] == Double.class)
                cellValue = new Double (
                                results.getDouble (columnNames[i]));
                        else if (columnClasses[i] == java.sql.Date.class)
                cellValue = results.getDate (columnNames[i]);
                        else
                System.out.println ("Can't assign " +
                                columnNames[i]);
                        cellList.add (cellValue);
                }// for
                Object[] cells = cellList.toArray();
                rowList.add (cells);
        } // while
        // finally create contents two-dim array
        contents = new Object[rowList.size()] [];
        for (int i=0; i<contents.length; i++)

                contents[i] = (Object []) rowList.get (i);
        System.out.println ("Created model with " +
                           contents.length + " rows");

        // close stuff
        results.close();
        statement.close();

        }
        // AbstractTableModel methods
        public int getRowCount() {
                return contents.length;
        }

        public int getColumnCount() {
                if (contents.length == 0)
                        return 0;
                else
                        return contents[0].length;
                }

                public Object getValueAt (int row, int column) {
                        return contents [row][column];
                }

                // overrides methods for which AbstractTableModel
                // has trivial implementations

                public Class getColumnClass (int col) {
                        return columnClasses [col];
                }

                public String getColumnName (int col) {
                        return columnNames [col];
                }
        }
  構造函數將實際的工作交給了getTableContents()方法,它負責剛才所提到的兩次查詢。通過連接得到DatabaseMetaData類的對象,之后調用getColumns()函數得到字段信息。這個方法的參數是catalog,schemaPattern,tableNamePattern,columnNamePattern;這里忽略了catalog,schemaPattern,然而假如你用的是一個復雜的數據庫,可能你就需要具體的描述這兩項。getColumns()返回一個結果集ResultSet,就像通常JDBC查詢得到的結果集一樣,對它進行迭代就可以了。
  要得到字段名是很輕易的:只需要調用getString("COLUMN_NAME")方法就可以了。但要得到數據類型就要有趣得多,當調用getInt("DATA_TYPE")時會返回一個int型數據,該類型是java.sql.Types類的常數之一。在上例中,我們只是簡單地將字符串類型和基本的數字類型恰當的映射到Java類中。TIMESTAMP是SQL中的一個有關時間(日期和時間)的類型,因此,要將它映射到Java的Date類。知道這些數據正確的數據類型將會使你更輕易并且能夠更準確的使用相應的getXXX()方法來檢索實際的表中的數據。

  第二次查詢是一個簡單的查詢語句SELECT * FROM tableName。由于查詢中沒有WHERE子句的約束,這將會得到表中所有記錄組成的結果集ResultSet。我應該不需要提到下面這些,就是假如tableName是一張有數以百萬計的記錄的表,你生成的表控件模型就將無法存放到內存中。你應該知道這些的,對嗎?

  此外,你需要對結果集ResultSet進行迭代。每次假如results.next()返回true,則表示還有結果,此前在查詢元數據的時候我們就已經清楚地知道表中每個字段信息了。這意味著在查詢數據時需要調用getXXX()方法并且將字段名作為參數傳入該方法,而且在此前的查詢中,我們已經很清楚哪個字段應該使用哪一個getXXX()方法。因為Jtables有基于類的解析機制,它可以將數據中的數字轉換成合適的類型(如Integer、Double等等)。你可能需要決定使用TableCellRenderer并通過Format類對表中所有的Double類型的數據進行格式化,即以特定的小數格式來格式化數字,或者將日期轉換成"今天"或"在25個小時以前"這類與時間或日期相關的詞,并在模型中對這類數據加粗顯示會非常有用。

  當查詢結束后,你需要將ArrayList轉換成數組。(數組一般提供能夠快速查找到元素的方法)。AbstractTableModel類中的抽象方法的實現在前面已經提到過了,連同getColumnClass()和getColumnName()實現的覆蓋和優化,columnNames,columnClasses和由該方法創建的內容數組contents的簡單使用也講完了。

測試

  在你說"我不能運行這個例子,我沒有數據庫"之前,先別急!開源世界有你想要的東西。而且并不像Jboss那樣那么大。HSQLDB,它原來的名字可能更被人所知,Hypersonic,這是一個用Java寫的JDBC關系數據庫引擎。它很小而且能夠獨自運行或在你的Java虛擬機里面運行。你可以到http://hsqldb.sourceforge.net/上下載HSQLDB。

  無論你用的是什么數據庫,你都需要一個驅動程序的名字,URL,用戶名和密碼來建立與數據庫的連接。假如你已經擁有一個數據庫了,我相信你應該很清楚這些。假如你剛下載了剛才所說的HSQLDB,你將會用到下列的信息:
¨        驅動程序:org.hsqldb.jdbcDriver
¨        URL:jdbc:hsqldb:文件:testdb
¨        用戶名:sa
¨        密碼:(空)

  假設你將HSQL添加為你的應用程序的一部分,這就需要你在classpath中添加上hsqldb.jar文件。你可能注重到,這將會在當前目錄中產生一個testdb文件,之后你可以將其刪除掉。你也可以給出其他的目錄的全路徑;具體的信息請參照HSQLDB的相關文檔。
  這個測試程序所期望的連接數據庫的字符串的形式要像屬性(properties)文件中的一樣,如jdbctable.driver,jdbctable.url,jdbctable.user和jdbctable.pass。為了使之更方便一些,有二個方法將這些信息傳入程序中:或者通過系統屬性(通常在Java命令后加上參數-D來指定),或者寫在一個叫jdbctable.properties的文件中。書上的源代碼中有一個設置HSQLDB默認值的例子用的就是第二種方法。

  為了測試JDBCTableModel,TestJDBCTable在數據庫中生成了一個新的完整的表。該模型得到數據庫的連接和這個表的表名以及數據庫中的數據。然后測試類只是簡單的利用模型創建一個JTable而且把它放入到JFrame中。例3-13給出了這個例子的源代碼。

例子3-13.測試基于JDBC的表控件
        import javax.swing.*;
        import javax.swing.table.*;
        import java.sql.*;
        import java.util.*;
        import java.io.*;
        public class TestJDBCTable {
                public static void main (String[] args) {
                        try {

                /*
                 driver, url, user, and pass can be passed in as
                 system properties "jdbctable.driver",
                 "jdbctable.url", "jdbctable.user", and
                 "jdbctable.pass", or specified in a file
                 called "jdbctable.properties" in current
                 Directory
                */
                Properties testProps = new Properties();
                String ddriver = System.getProperty ("jdbctable.driver");
                String durl = System.getProperty ("jdbctable.url");
                String duser = System.getProperty ("jdbctable.user");
                String dpass = System.getProperty ("jdbctable.pass");

                if (ddriver != null)
                        testProps.setProperty ("jdbctable.driver", ddriver);
                if (durl != null)
                        testProps.setProperty ("jdbctable.url", durl);
                if (duser != null)
                        testProps.setProperty ("jdbctable.user", duser);
                if (dpass != null)
                        testProps.setProperty ("jdbctable.pass", dpass);
                try {
                        testProps.load (new FileInputStream (
                                        new File ("jdbctable.properties")));
                } catch (Exception e) {} // ignore FNF, etc.
                System.out.println ("Test Properties:");
                testProps.list (System.out);
                // now get a connection
                // note care to replace nulls with empty strings
                Class.forName(testProps.getProperty
                                ("jdbctable.driver")).newInstance();
                String url = testProps.getProperty ("jdbctable.url");
                url = ((url == null) ? "" : url);
                String user = testProps.getProperty ("jdbctable.user");
                user = ((user == null) ? "" : user);
                String pass = testProps.getProperty ("jdbctable.pass");
                pass = ((pass == null) ? "" : pass);

                Connection conn =
                        DriverManager.getConnection (url, user, pass);
                // create db table to use
                String tableName = createSampleTable(conn);

                // get a model for this db table and add to a JTable
                TableModel mod =
                        new JDBCTableModel (conn, tableName);
                JTable jtable = new JTable (mod);
                JScrollPane scroller =
                        new JScrollPane (jtable,
                                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
                JFrame frame = new JFrame ("JDBCTableModel demo");
                frame.getContentPane().add (scroller);
                frame.pack();
                frame.setVisible (true);

                conn.close();

                        } catch (Exception e) {
                e.printStackTrace();
                        }
                }

                public static String createSampleTable (Connection conn)
                        throws SQLException {

                        Statement statement = conn.createStatement();
                        // drop table if it exists
                        try {

                statement.execute ("DROP TABLE EMPLOYEES");
                        } catch (SQLException sqle) {
                sqle.printStackTrace(); // if table !exists
                        }
                        
                        statement.execute ("CREATE TABLE EMPLOYEES " +
                                   "(Name CHAR(20), Title CHAR(30), Salary INT)");
                        statement.execute ("INSERT INTO EMPLOYEES VALUES " +
                                   "('Jill', 'CEO', 200000 )");
                        statement.execute ("INSERT INTO EMPLOYEES VALUES " +
                                   "('Bob', 'VP', 195000 )");
                        statement.execute ("INSERT INTO EMPLOYEES VALUES " +
                                       "('Omar', 'VP', 190000 )");
                        statement.execute ("INSERT INTO EMPLOYEES VALUES " +
                                   "('Amy', 'Software Engineer', 50000 )");
                        statement.execute ("INSERT INTO EMPLOYEES VALUES " +
                                   "('Greg', 'Software Engineer', 45000 )");

             statement.close();
                 return "EMPLOYEES";
                 }
        }

  createSampleTable()方法就是你需要重寫的來插入你自定義數據的方法。實際上,由于它返回的是你所創建的表的表名,你需要在數據庫中創建許多不同的表來測試模型如何處理他們?;蛘呃靡粋€循環生成多行數據并且看裝載這些數據需要多長時間。
  最后,當你運行程序的時候,TestJDBCTable生成了一個帶有數據庫表的內容的JFrame,如圖3-9所示。

Hacking swing: 一個JDBC表控件模型
圖3-9.將數據庫中的數據填充到Jtable中

Joshua Marinacci是java.net上" The Java Sketchbook "的專欄作家,范圍涉及Java客戶端和網絡編程。
Chris Adamson是ONJava和java.net的編輯,亞特蘭大顧問,主攻Java,Mac操作系統X和多媒體編程。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美日韩直播| 日本精品视频在线| 热久久视久久精品18亚洲精品| 91精品视频播放| 欧美在线视频一二三| 亚洲精品一区二区久| 国产精品自产拍在线观看| 久久久久一本一区二区青青蜜月| 一区二区成人精品| 国产日韩精品电影| 3344国产精品免费看| 九九九久久国产免费| 欧美成在线观看| 国产视频精品免费播放| 国产精品视频精品| 久久久亚洲影院| 日本高清+成人网在线观看| 亚洲三级av在线| 亚洲人成自拍网站| 欧美视频免费在线| 国产成人av网址| 热99精品只有里视频精品| 日韩av网址在线观看| 久久久久久久久爱| 欧美亚洲另类制服自拍| 欧美精品videosex性欧美| 久久成人免费视频| 91影视免费在线观看| 国产精品高潮粉嫩av| 欧美猛男性生活免费| 欧美电影《睫毛膏》| 欧美日韩中文字幕在线视频| 欧美性猛交xxxx富婆| 中文字幕亚洲欧美日韩在线不卡| 亚洲国产精品小视频| 国产精品欧美激情| 91香蕉国产在线观看| 日韩视频精品在线| www.久久久久久.com| 国产一区二区三区日韩欧美| 欧美一级bbbbb性bbbb喷潮片| 亚洲免费伊人电影在线观看av| 精品中文字幕乱| 日韩av观看网址| 亚洲第一偷拍网| 欧美午夜宅男影院在线观看| 操人视频在线观看欧美| 久久五月天综合| 日韩高清有码在线| 国产日产久久高清欧美一区| 久久亚洲精品中文字幕冲田杏梨| 国产精品久久久久久久久男| 日韩精品视频在线观看免费| 国产精品国产福利国产秒拍| 日韩精品中文字幕视频在线| 日韩欧美在线视频免费观看| 亚洲色图av在线| 人人爽久久涩噜噜噜网站| 亚洲精品在线观看www| 欧美性猛交xxxx富婆弯腰| 国产精品pans私拍| 性欧美xxxx视频在线观看| 国内精品久久久久影院优| 欧美成人精品一区二区三区| 日韩精品久久久久久福利| 国产成人免费av| 国产欧美亚洲视频| 日本久久久久久久久| 97视频在线看| 久久久久久中文字幕| 2021久久精品国产99国产精品| 国产福利精品在线| 国产精品成人久久久久| 国产精品尤物福利片在线观看| 久久久久久久久久久av| 清纯唯美日韩制服另类| 日韩中文视频免费在线观看| 亚洲女人天堂成人av在线| 日韩成人激情在线| 亚洲国产精品成人av| 91夜夜未满十八勿入爽爽影院| 国产一区二区三区视频| 欧美成人三级视频网站| 久久福利视频网| 欧美另类极品videosbestfree| 成人有码在线视频| 在线视频欧美性高潮| 亚洲精品网址在线观看| 亚洲欧美日韩在线一区| 亚洲男人的天堂在线| 最近更新的2019中文字幕| 国产成人短视频| 欧美尤物巨大精品爽| 另类天堂视频在线观看| 96sao精品视频在线观看| 91精品国产高清| 日韩av免费在线播放| 亚洲另类图片色| 亚洲成人黄色网址| 69精品小视频| 亚洲一区中文字幕在线观看| 成人情趣片在线观看免费| 国产精品久久久久久久久久久不卡| 欧美日韩在线观看视频| 91国自产精品中文字幕亚洲| 日韩美女免费观看| 18一19gay欧美视频网站| 亚洲天堂av在线免费| 日韩在线观看免费全集电视剧网站| 中文在线资源观看视频网站免费不卡| 岛国av一区二区三区| 日韩免费电影在线观看| 国产91在线播放精品91| 久久国产精品影视| 精品国产自在精品国产浪潮| 亲爱的老师9免费观看全集电视剧| 精品久久久国产| 亚洲免费视频一区二区| 国产精品爱久久久久久久| 色一情一乱一区二区| 色系列之999| 国产视频亚洲精品| 伊人久久综合97精品| 亚洲激情视频网站| 亚洲综合一区二区不卡| 中文字幕亚洲欧美一区二区三区| 久久91精品国产| 国产激情久久久| 91伊人影院在线播放| 韩国v欧美v日本v亚洲| 欧美电影院免费观看| 精品人伦一区二区三区蜜桃网站| 精品国内亚洲在观看18黄| 日韩精品视频免费在线观看| 亚洲美女精品成人在线视频| 欧美丰满片xxx777| 国产视频精品va久久久久久| 一道本无吗dⅴd在线播放一区| 久久视频在线看| 久操成人在线视频| 国产精品成人国产乱一区| 日韩精品免费在线视频| 欧美肥老妇视频| 日本欧美爱爱爱| 自拍偷拍亚洲精品| 在线精品高清中文字幕| 尤物九九久久国产精品的特点| 亚洲欧美日韩一区二区三区在线| 国产日韩欧美在线观看| 疯狂做受xxxx高潮欧美日本| 亚洲欧美精品中文字幕在线| 2019亚洲男人天堂| 亚洲第一精品夜夜躁人人躁| 精品伊人久久97| 色综合久综合久久综合久鬼88| 欧美超级乱淫片喷水| 欧美激情亚洲激情| 最好看的2019的中文字幕视频| 91av在线免费观看视频| 色偷偷噜噜噜亚洲男人| 亚洲欧美日本伦理| 成人免费看吃奶视频网站| 成人黄色在线播放| 亚洲视频免费一区|