




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、PAGE 222Eclipse從入門到精通PAGE 101第9章 圖書進存銷系統(tǒng)第9章 圖書進存銷系統(tǒng)第9章圖書進存銷系統(tǒng)9.1 項目簡介本章介紹如何開發(fā)一個CS結構的圖書進存銷系統(tǒng),該系統(tǒng)的主要有出版社管理、書本管理、書的入庫管理、銷售管理等功能,通過這些簡單的功能,可以讓我們了解如何利用JDBC進行數(shù)據(jù)庫操作、如何使用Java的反射機制以及如何對系統(tǒng)進行分層等知識點。9.2建立界面在實現(xiàn)功能前,我們需要為這個系統(tǒng)建立界面和設計數(shù)據(jù)庫,本小節(jié)將建立在這個小系統(tǒng)中所需要的各個界面。9.2.1登錄界面在進入系統(tǒng)前,我們需要經(jīng)過簡單的認證才能進入,因此需要提供一個簡單的登錄界面,當輸入用戶名和密碼
2、都正確時,就可以進入系統(tǒng)。需要建立的登錄界面如圖9.1所示。圖9.1 登錄界面界面非常的簡單,只是兩個輸入框,一個按鈕即可實現(xiàn)。帳號輸入框使用的是JTextField類,而密碼輸入框使用的是JPasswordField類,使用JPasswordField對象并不會顯示原始輸入的字符。在本章中,我們將在最后再去實現(xiàn)用戶的登錄,先去實現(xiàn)系統(tǒng)的銷售和入庫功能。9.2.2 銷售管理界面銷售管理界面主要用于進行書的銷售操作,添加一本需要交易的書、從交易列表中移除該書、進行交易等操作,在本界面的上半部分為交易記錄列表,我們約定交易記錄列表所顯示的為今天進行的交易,并提供一個輸入日期的輸入框,可以根據(jù)日期進
3、行查詢該天的交易記錄。本界面的下半部分為顯示某筆交易的具體信息,包括該筆交易所涉及的金額、銷售量、交易日期、交易所涉及的書等信息。初步的界面如圖9.2所示。圖9.2 銷售界面如圖9.2,銷售管理界面的交易記錄列表中,每列的字段分別為該交易所涉及的書本名、總價、交易日期、總數(shù)量。銷售管理界面的下面部分,是顯示具體某筆交易的界面,顯示對應某筆交易的總價、交易日期、總數(shù)量、交易涉及書的列表,其中交易中涉及書的列表中,包括書的書名、單價、和本次交易中該本書出售的數(shù)量。交易中涉及的書列表下,可以選擇書和輸入書的數(shù)量,并提供添加和刪除按鈕,當選擇了一本書并輸入相應的交易數(shù)量,再點擊添加時,即可向交易涉及的
4、書列表中添加書的記錄,當然也可以進行刪除操作。在界面的最上面,有一個查詢按鍵,可以輸入日期進行交易記錄查詢。注:具體某筆交易的界面(界面的下面部分),總價、交易日期和總數(shù)量是不可輸入的,這是由于總價是由各本書的單價乘以交易數(shù)量得出來的,交易日期是當前交易時系統(tǒng)的時間為準的,總數(shù)量是各本書的交易數(shù)量總和,因此并不需要人手進行輸入。另外,如果在書本的下拉框中選擇了某本書時,將會帶出該本書的單介和庫存,好讓使用者在操作時對該本書的狀況有所了解。在本例中,每一個界面對應一個JPanel,每個界面都是一個JPanel類的子類,銷售管理界面里面是一個JSplitPane對象,上面放一個個JScrollPa
5、ne對象,下面部分也是一個JScrollPane對象。上面的JScrollPane對象主要存放一個JTable,下面的JScrollPane主要放一些Box對象進行布局,詳細請看圖書進存銷系統(tǒng)代碼清單中的SalePanel類。9.2.3入庫管理界面入庫管理界面和銷售管理界面的布局大致相同,只是其中的數(shù)據(jù)列和文字有所差距。入加管理界面如圖9.3所示。圖9.3 庫存管理界面與銷售管理界面類似,上面的列表是入庫記錄,一條入庫記錄包括入庫時所涉及的書本、入庫日期和入庫書本的總數(shù)量。界面下面部分是具體某條入庫記錄的具體信息,包括入庫日期、總數(shù)量和入庫書本的列表,同樣地,入庫日期與總數(shù)量都不可以手動輸入。
6、在新增一條入庫記錄時,可以向書本列表添加和刪除書本,表示該入庫記錄中所涉及的書本及對應的數(shù)量。注:在選擇某本書時,需要自動帶出該書的庫存。在本例中,入庫管理界面對應的類為RepertoryPanel類,是JPanel的子類。9.2.4 書本管理界面書本管理界面主要包括書本的查詢、列表、查看等功能,書本在本例中作為基礎數(shù)據(jù)的角色,主要用于銷售和入庫。這里需要注意的是,在新增一本書的時候,該書的庫存為0,只有經(jīng)過銷售和入庫才會對書的庫存量產(chǎn)生影響。書的基本信息除了書名、價格介紹、所屬出版社和書的種類外,還需要有書的圖片,為簡單起見,本例中的每本書只有一張圖片,因此不需要另外建立表來存放書的圖片。書
7、本管理界面如圖9.4所示。圖9.4 書本管理界面書本管理界面上面的列表主要顯示書本名稱、簡介、所屬種類、出版社、庫存數(shù)量和價格這些信息,此處的書本名稱與銷售管理(入庫管理)界面中的書本名稱有所區(qū)別,這里的書本名稱的列寬較窄,這是由于銷售(入庫)中所涉及的是多本書,而書本管理界面中每一條書的記錄只是代表一本書。在界面的下方有一個表單,用于查看、修改和添加書本操作,表單的右邊是書的圖片顯示區(qū),用于顯示書本所對應的縮略圖,當用戶點擊縮略圖的時候,可以彈出新的窗口用于展示大圖。與前面的界面一樣,在程序中,我們新增一個BookPanel作為該界面。9.2.5 種類管理界面書的種類,表示一本書是屬于哪個種
8、類的,例如計算機、文學、法律等等,這些都是書的種類,我們提供一個種類管理界面,可以用于管理各個種類。種類在本例中與書本一樣,屬于基礎數(shù)據(jù)。新增種類并不需要任何約束,只需要輸入種類的名稱即可。在書的管理界面中,如果需要添加一本書,必須選擇該書所對應的種類。種類管理界面如圖9.5所示。圖9.5 種類管理界面如圖9.5所示,種類管理界面并不復雜,上面是一個簡單的列表,下面是普通的查看、新增與修改的表單。在程序中,我們新增一個TypePanel作為該界面。9.2.6 出版社管理界面添加一本書,除了需要有種類之外,還需要選擇該書的出版社,我們提供一個出版社管理界面。如圖9.6所示。圖9.6 出版社管理界
9、面出版社列表中,主要顯示出版社名稱、聯(lián)系人、x和簡介這些信息,下面的表單與前面幾個界面的表單類似,都是用于查看、修改和新增。在程序中,我們新增一個ConcernPanel來表示這個界面。從9.2.2到9.2.6的各個系統(tǒng)界面,都是存在于一個JFrame中,我們可以提供菜單,當點擊了某個菜單的時候,JFrame中的各個JPanel對象隱藏,只顯示對應的那個JPanel。到此,我們所需要的界面已經(jīng)全部完成了,在9.2.7中我們將對各個界面的代碼進行優(yōu)化,再去為主界面加上相應的菜單,我們的界面就全部完成。9.2.7 修改界面代碼本例中涉及的各個界面,我們可以發(fā)現(xiàn)界面幾乎都大同小異,界面上面部分是一個
10、列表,下面是一個表單,因此,我們可以將這幾個界面的共同部分提取出來,作為每個界面對象(JPanel)的父類,將一些可以重用的代碼提升至父類,并可以使用“模板方法”,提供一些抽象的方法讓各個子類去實現(xiàn)。以下代碼為各個界面對象的父類(CommonPanel)的代碼。代碼清單:codebooksrcorgcrazyitbookuiCommonPanel.javaprivate JTable table;/存放數(shù)據(jù)的tableprotected Vector datas;/列表數(shù)據(jù)public void setJTable(JTable table) this.table = table;public
11、 JTable getJTable() return this.table;public Vector getDatas() return datas;public void setDatas(Vector datas) this.datas = datas;/將數(shù)據(jù)設置進JTable中public void initData() if (this.table = null) return; DefaultTableModel tableModel = (DefaultTableModel)this.table.getModel();/將數(shù)據(jù)設入表格Model中tableModel.setDa
12、taVector(getDatas(), getColumns();/設置表格樣式setTableFace();/刷新列表的方法public void refreshTable() initData();getJTable().repaint();/獲取表列集合, 由子類去實現(xiàn)public abstract Vector getColumns();/設置列表的樣式, 由子類去實現(xiàn)public abstract void setTableFace();/設置數(shù)據(jù)列表的方法,由子類去實現(xiàn)public abstract void setViewDatas();/清空界面下邊的列表public abs
13、tract void clear();/給子類使用的方法, 用于獲取一個列表的id列值public String getSelectId(JTable table) int row = table.getSelectedRow();int column = table.getColumn(id).getModelIndex();String id = (String)table.getValueAt(row, column);return id;以上的代碼,提供一個JTable的屬性,這是因為每個界面中都有一個主要的列表對象,例如銷售管理界面中的銷售記錄列表、書本管理界面中的書本列表等。注意代
14、碼中的黑體部分,都是由子類去實現(xiàn)的方法,getColumns()由子類去提供列表的列集合;setTableFace()是由子類去設置JTable的顯示,例如需要設置某一列的寬度或者設置列表的行高等等;而setViewDatas()方法是重新去數(shù)據(jù)庫讀取數(shù)據(jù),由子類去實現(xiàn);clear()方法是刷新每個界面下邊的表單,同樣由子類去實現(xiàn)。在CommonPanel中提供了一個getSelectId方法,用來獲得JTable屬性中所選中的某一行中id列的值,也就是意味著在列表中,必須要有一個列名叫做id的列。父類定義好規(guī)范之后,子類就可以根據(jù)不同的情況,給父類不同的列,讓父類進行顯示,除了需要提供列的集
15、合外,還需要提供數(shù)據(jù),也就是CommonPanel中的datas屬性。我們這里提供了一個setViewDatas的方法,主要從數(shù)據(jù)庫中讀取相關的數(shù)據(jù),再調(diào)用父類的initDatas方法構建列表。那么存放各個界面對象的JFrame類中,可以提供一個方法,當界面發(fā)生轉換時,就調(diào)用setViewDatas方法,具體代碼如下。代碼清單:codebooksrcorgcrazyitbookuiMainFrame.java/切換各個界面private void changePanel(CommonPanel commonPanel) /移除當前顯示的JPanelthis.remove(currentPane
16、l);/添加需要顯示的JPanelthis.add(commonPanel);/設置當前的JPanelthis.currentPanel = commonPanel;this.repaint();this.setVisible(true);/調(diào)用CommonPanel的方法重新讀取數(shù)據(jù)并刷新列表commonPanel.setViewDatas ();/清空界面下邊的表單commonPanel.clear();以上代碼的黑體部分,調(diào)各個界面對象父類的setVieweDatas方法重新讀取數(shù)據(jù)并刷新列表,各個界面中轉換時,當點擊了對應的菜單后,再進行轉換(調(diào)用changePanel方法)。代碼清單
17、:codebooksrcorgcrazyitbookuiMainFrame.javaprivate Action sale = new AbstractAction(銷售管理, new ImageIcon(images/sale.gif) public void actionPerformed(ActionEvent e) /調(diào)用轉換的方法changePanel(salePanel);以上代碼表示點擊了銷售管理的菜單后,就調(diào)用changePanel方法,轉換界面并初始化數(shù)據(jù)。另外,每個界面的主列表我們使用一個CommonJTable對象,該對象繼承于JTable,我們并不需要讓列表的每個單元格
18、可以編輯,因此重寫JTable的isCellEditable方法即可,代碼如下。代碼清單:codebooksrcorgcrazyitbookuiCommonJTable.javapublic class CommonJTable extends JTable public CommonJTable(TableModel dm) super(dm);/設置表格只能選擇一行getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); /重寫父類的方法, 使所有的單元格不可編輯public boolean isC
19、ellEditable(int row, int column) return false;做了以上的準備工作后,就可以修改各個界面對應的類,去繼承CommonPanel即可,實現(xiàn)getColumns()、setTableFace()、setViewDatas()和clear()方法,而數(shù)據(jù)暫時不必提供,下一節(jié)我們將開始設計數(shù)據(jù)庫。9.3 設計系統(tǒng)數(shù)據(jù)庫在9.2中我們已經(jīng)建立了系統(tǒng)的相關界面,接下來,這一小節(jié)將設計這個系統(tǒng)的數(shù)據(jù)庫。本例使用的是MySQL5.0作為數(shù)據(jù)庫。在設計數(shù)據(jù)庫前,我們可以確定,系統(tǒng)相關的表,從最基礎開始,有出版社表、書的類型表、書表、入庫記錄表和銷售記錄表,其中,一條入
20、庫記錄中涉及多本書,一條銷售記錄也涉及多本書,因此還需要書的入庫記錄表和書的銷售記錄表,一條書的入庫記錄對應一本書,該條書的入庫記錄屬于某一條入庫記錄,可以理解成這是書與入庫記錄的關系表,同樣地,書的銷售記錄與書的入庫記錄一樣。如果上面的文字難以理解,可以看下面的數(shù)據(jù)庫結構,更有助于理解。在設計各個表前,我們需要創(chuàng)建數(shù)據(jù)庫,在MySQL中,創(chuàng)建BOOK_SYSTEM數(shù)據(jù)庫,具體的SQL語句如下:- 創(chuàng)建DATABASECREATE DATABASE IF NOT EXISTS BOOK_SYSTEM;- 使用BOOK_SYSTEMUSE BOOK_SYSTEM;MySQL中的CREATE和US
21、E語法可查看MySQL的幫助文檔。9.3.1 設計出版社表在9.2.6中,我們已經(jīng)建立了出版社的管理界面,現(xiàn)在只需要根據(jù)界面來設計數(shù)據(jù)庫即可。我們在MySQL中建立表T_PUBLISHER,出版社表包括的字段有:ID:主鍵ID。PUB_NAME:出版社名稱。PUB_TEL:x。PUB_LINK_MAN:聯(lián)系人。PUB_INTRO:出版社簡介。由于出版社是最基礎的數(shù)據(jù),因此不需要其他的外鍵關系。以下為創(chuàng)建T_PUBLISHER這個表的SQL。- 出版社CREATE TABLE IF NOT EXISTS T_PUBLISHER ( ID int AUTO_INCREMENT NOT NULL,
22、- 主鍵生成策略為自動增長 PUB_NAME varchar(50), - 出版社名稱 PUB_TEL varchar(50), - x PUB_LINK_MAN varchar(50), - 聯(lián)系人 PUB_INTRO varchar(200), - 簡介 PRIMARY KEY (ID) - 聲明主鍵);如果你有MySQL的一些管理工具,可以使用這些工具進行創(chuàng)建表,并不需要自己書寫SQL語句,但筆者還是希望能夠自己嘗試去編寫這些SQL,因為對于初學者而言,可以自己去編寫這些SQL,無疑是對自己能力的一種提高。9.3.2 設計種類表種類表與出版社表一樣,并不復雜,也沒有任何的外鍵,根據(jù)9.2
23、.5的界面,就可以確定需要哪些字段了。創(chuàng)建T_BOOK_TYPE表,包括以下的字段:ID:主鍵IDTYPE_NAME:種類的名稱。TYPE_INTRO:種類的簡介。只有簡單的三個字段,創(chuàng)建的SQL如下。- 書種類CREATE TABLE IF NOT EXISTS T_BOOK_TYPE ( ID int AUTO_INCREMENT NOT NULL, - 主鍵生成策略為自動增長 TYPE_NAME varchar(50), - 種類名稱 TYPE_INTRO varchar(200), - 種類簡介 PRIMARY KEY (ID);9.3.3 設計書表在9.2.4的界面中,我們可以看到,
24、一本書所需要的字段包括:書名、簡介、作者、所屬種類、出版社、縮略圖地址、庫存和價格,種類表和出版社表已經(jīng)在9.3.2與9.3.1中設計了,只需要為書表添加外鍵關系即可,新增表T_BOOK,以下為書表各個字段的描述:ID:主鍵IDBOOK_NAME:書的名字。BOOK_INTRO:書的簡介。BOOK_PRICE:書的單價。TYPE_ID_FK:書所屬的種類ID外鍵。PUB_ID_FK:出版社外鍵。IMAGE_URL:縮略圖的地址。AUTHOR:作者名稱。REPERTORY_SIZE:庫存量。這里需要注意一下,書的名字、簡價、單價、所屬的種類、出版社、縮略圖和作者,都可以在界面中通過輸入或者選擇寫
25、入到數(shù)據(jù)庫中,但是庫存量是由銷售與入庫決定的,因此在修改書的時候,不可以設置書的庫存量。創(chuàng)建該表的SQL如下。- 書CREATE TABLE IF NOT EXISTS T_BOOK ( ID int AUTO_INCREMENT NOT NULL, - ID字段,自增 BOOK_NAME varchar(50), - 書名稱 BOOK_INTRO varchar(200), - 書簡介BOOK_PRICE double, - 書的單價 TYPE_ID_FK int NOT NULL, - 種類外鍵 PUB_ID_FK int NOT NULL, - 出版社外鍵IMAGE_URL varcha
26、r(200), - 縮略圖URLAUTHOR varchar(200), - 作者 REPERTORY_SIZE bigint(10), - 庫存數(shù)量 FOREIGN KEY (TYPE_ID_FK) REFERENCES T_BOOK_TYPE (ID), - 聲明種類的外鍵 FOREIGN KEY (PUB_ID_FK) REFERENCES T_PUBLISHER (ID), - 聲明出版社外鍵 PRIMARY KEY (ID);9.3.4 設計入庫記錄表在設計入庫記錄前,我們需要知道的是,一個入庫記錄,包含多本書的入庫,也就是說,一次入庫,有可能入庫多本書。入庫記錄,只需要記錄入庫的時
27、間即可,新建T_IN_RECORD表,該表的字段如下:ID:主鍵ID。RECORD_DATE:入庫日期。以下為創(chuàng)建該表的SQL。- 入庫記錄表, 一次入庫會入多本書CREATE TABLE IF NOT EXISTS T_IN_RECORD ( ID int AUTO_INCREMENT NOT NULL, RECORD_DATE datetime, - 入庫日期 PRIMARY KEY (ID);設計完入庫記錄后,我們還需要考慮,一次入庫涉及了多本書,因此需要添加一個關系表,用來表示一次入庫中所涉及的書。創(chuàng)建T_BOOK_IN_RECORD表,該表的字段如下:ID:該表的主鍵IDBOOK_I
28、D_FK:書的外鍵,表示這一條書的入庫記錄所對應的書。T_IN_RECORD_ID_FK:入庫記錄的外鍵,表示這一條書的入庫記錄所對應的是哪一次入庫,這個關系也表示了一次入庫可以有多條書的入庫記錄。IN_SUM:這一條書的入庫記錄中對應的書的入庫數(shù)量。創(chuàng)建的SQL語句如下。- 書的入庫記錄CREATE TABLE IF NOT EXISTS T_BOOK_IN_RECORD ( ID int AUTO_INCREMENT NOT NULL, - ID自增 BOOK_ID_FK int, - 入庫的書 T_IN_RECORD_ID_FK int, - 對應的入庫記錄 IN_SUM int(10)
29、, - 入庫數(shù)量 FOREIGN KEY (BOOK_ID_FK) REFERENCES T_BOOK (ID), - 聲明書的外鍵 FOREIGN KEY (T_IN_RECORD_ID_FK) REFERENCES T_IN_RECORD (ID), - 聲明入庫記錄外鍵 PRIMARY KEY (ID);注:在入庫表中,并沒有提供入庫總數(shù)量這個字段,這是由于入庫總數(shù)量是各本書的入庫數(shù)量的總和。因此并不需要在數(shù)據(jù)庫中提供字段,只需要在程序中進行計算即可。創(chuàng)建完了這兩個表之后,就完成了書的入庫相關表的設計。9.3.5 設計銷售記錄表銷售記錄表與入庫記錄表大同小異,都是需要創(chuàng)建一個銷售表,再創(chuàng)
30、建書的銷售表。一條銷售記錄對應多條書的銷售記錄,一次銷售所涉及多本書,與入庫記錄一樣,都通過一個中關系表來體現(xiàn)這種關系。銷售記錄表的字段如下:ID:ID主鍵。RECORD_DATE:交易日期。創(chuàng)建該表的SQL如下。- 交易記錄表, 一個交易記錄包括多個書的銷售記錄, 一次交易可能有多本書CREATE TABLE IF NOT EXISTS T_SALE_RECORD ( ID int AUTO_INCREMENT NOT NULL, RECORD_DATE datetime,- 交易日期 PRIMARY KEY (ID);創(chuàng)建了交易表后,再去設計書的交易表,具體字段與書的入庫記錄表相似:ID:
31、主鍵IDBOOK_ID_FK:該條書的交易記錄所對應的書。T_SALE_RECORD_ID_FK:該條書的交易記錄所對應的交易記錄。TRADE_SUM:該記錄中對應的書的交易數(shù)量。創(chuàng)建書的入庫記錄表的SQL如下。- 書的銷售記錄, 一條記錄對應一本書CREATE TABLE IF NOT EXISTS T_BOOK_SALE_RECORD ( ID int AUTO_INCREMENT NOT NULL, BOOK_ID_FK int, - 銷售的書 T_SALE_RECORD_ID_FK int, - 該書的銷售記錄所對應的交易記錄 TRADE_SUM int(10), - 銷售數(shù)量 FOR
32、EIGN KEY (BOOK_ID_FK) REFERENCES T_BOOK (ID), FOREIGN KEY (T_SALE_RECORD_ID_FK) REFERENCES T_SALE_RECORD (ID), PRIMARY KEY (ID);注:交易表中并沒有提供交易總價和交易總數(shù)量這兩個字段,這是由于這兩個值是由各本書的交易量所決定的。到此,數(shù)據(jù)庫各個表的結構已經(jīng)設計完成了,各個表的結構都十分簡單,只有庫存與銷售兩個模塊的表相對復雜了一點。在下一節(jié)中,我們將講解如何使用Java的反射進行對象與表的映射與使用JDBC進行數(shù)據(jù)庫操作等知識。9.4 開發(fā)前的準備工作在9.3小節(jié)中,數(shù)
33、據(jù)庫已經(jīng)設計好了,接下來可以準備開發(fā)的工作了。其實當設計好數(shù)據(jù)庫,我們就可以進行開發(fā),本小節(jié)中所講的開發(fā)準備工作,是指編寫一些公用的方法,例如JDBC的基本操作,包括查詢、修改等。將一些可以重用的代碼先編寫好,再去進行業(yè)務開發(fā),到業(yè)務開發(fā)的時候,可以事半功倍。9.4.1 設計表的對應類在9.3中,已經(jīng)設計了系統(tǒng)所需要的各個表,包括出版社表、書種類表、書表等,那么現(xiàn)在,我們需要為這些表建立相應的對象,每一個表可以對應一個對象??梢詾槊總€表的對象先建立一個父類,由于每個表中都有ID一列,因此我們可以建立一個父類,提供ID字段。新建各個表對應對象的父類ValueObject,ValueObject的
34、代碼如下。代碼清單:codebooksrcorgcrazyitbookvoValueObject.javapublic class ValueObject /ID字段,對應數(shù)據(jù)庫中的ID列private String ID;/省略setter和getter方法該類只提供了一個ID字段,并提供setter和getter方法,注意,ID屬性必須與數(shù)據(jù)庫中表的ID列名字對應,由于這個是各個表對象的父類,因此需要約定每個表的主鍵命名必須為ID,為什么需要這樣,在下面章節(jié)將會詳細講述。建立了父類ValueObject后,此時再去新建出版社所對應的實體Concern類,一個Concern對象代表一個出版社
35、,該類繼承于ValueObject,此外,出版社表中有的字段,都需要在這個類中反應出來。Concern類代碼如下。代碼清單:codebooksrcorgcrazyitbookvoConcern.javapublic class Concern extends ValueObject /出版社名稱private String PUB_NAME;/出版社電話private String PUB_TEL;/聯(lián)系人private String PUB_LINK_MAN;/簡介private String PUB_INTRO;/省略各個屬性的getter和setter方法注意各個屬性的命名,必須要與數(shù)據(jù)
36、庫中表的字段一致,由于繼承了ValueObject類,因此不需要提供ID字段。按照建立Concern對象的方法,再去建立Type對象、Book對象,Type代表書本類,Book代表書類型。在Book類中需要注意的是,由于書表中有兩個鍵,分別是種類的外鍵TYPE_ID_FK和出版社的外鍵PUB_ID_FK,同樣地也提供這兩個類屬性,并不是提供種類的對象(Type)和出版社的對象(Concern),另外所有屬性類型都需要為String。Type的代碼如下,代碼清單:codebooksrcorgcrazyitbookvoType.javapublic class Type extends Value
37、Object /名稱private String TYPE_NAME;/簡介private String TYPE_INTRO;/省略setter和getter方法Book的代碼如下,代碼清單:codebooksrcorgcrazyitbookvoBook.javapublic class Book extends ValueObject private String BOOK_NAME;/書本名稱private String BOOK_INTRO;/簡介private String BOOK_PRICE;/書的單價private String TYPE_ID_FK;/種類外鍵private
38、String PUB_ID_FK;/出版社外鍵private String REPERTORY_SIZE;/存儲量private String IMAGE_URL;/圖片url創(chuàng)建完三個基礎數(shù)據(jù)表所對應的類后,接下來再去創(chuàng)建入庫記錄表對應的類、書的入庫記錄表對應的類、銷售記錄表對應的類和書的銷售記錄表對應的類。入庫記錄類InRecord,代碼清單:codebooksrcorgcrazyitbookvoInRecord.javapublic class InRecord extends ValueObject private String RECORD_DATE;/入庫日期/省略getter和s
39、etter方法書的入庫記錄類BookInRecord,代碼清單:codebooksrcorgcrazyitbookvoBookInRecord.javapublic class BookInRecord extends ValueObject private String BOOK_ID_FK;/對應書的外鍵, 從數(shù)據(jù)庫查出來時有值private String T_IN_RECORD_ID_FK;/對應銷售記錄外鍵private String IN_SUM;/入庫數(shù)量/省略setter和getter方法銷售記錄類SaleRecord,代碼清單:codebooksrcorgcrazyitbook
40、voSaleRecord.javapublic class SaleRecord extends ValueObject private String RECORD_DATE;/交易日期/省略setter和getter方法書的銷售記錄類BookSaleRecord。代碼清單:codebooksrcorgcrazyitbookvoBookSaleRecord.javapublic class BookSaleRecord extends ValueObject private String BOOK_ID_FK;/該記錄對應的書的外鍵private String T_SALE_RECORD_ID
41、_FK;/該記錄對應的銷售記錄的外鍵private String TRADE_SUM;/該記錄所對應的書的銷售數(shù)量/省略setter和getter方法到現(xiàn)在,與系統(tǒng)相關的各個表所對應的類都已經(jīng)編寫好了,下面小節(jié),我們將講解這些建立好的類在開發(fā)過程中所體現(xiàn)的作用。9.4.2 編寫配置讀取類由于本章涉及到數(shù)據(jù)庫操作,因此與數(shù)據(jù)庫相關的一些配置,例如對應數(shù)據(jù)庫的相關驅動、數(shù)據(jù)庫地址、用戶名和密碼,我們可以放到配置文件中,如果需要更換數(shù)據(jù)庫或者地址,只需要修改這份配置文件即可。建立配置文件perties,內(nèi)容如下:/JDBC驅動jdbc.driver=com.mysql.jdbc.Dr
42、iver/連接地址jdbc.url=jdbc:mysql:/localhost:3306/book_system/數(shù)據(jù)庫用戶名jdbc.user=book/密碼jdbc.pass=book建立好該文件后,再編寫類去讀取該文件,獲得所需要的值即可。用于讀取配置的PropertiesUtil類,代碼如下。代碼清單:codebooksrcorgcrazyitbookjdbcPropertiesUtil.javapublic class PropertiesUtil private static Properties properties = new Properties();/該記錄所對應的書的銷售
43、數(shù)量private static String CONFIG = /cfg/perties;/配置文件的路徑/讀取資源文件, 設置輸入流private static InputStream is = PropertiesUtil.class.getResourceAsStream(CONFIG);public static String JDBC_DRIVER;/數(shù)據(jù)庫驅動public static String JDBC_URL;/jdbc連接urlpublic static String JDBC_USER;/數(shù)據(jù)庫用戶名public static String JDBC_
44、PASS;/數(shù)據(jù)庫密碼static properties.load(is);/加載輸入流/獲得配置的各個屬性JDBC_DRIVER = properties.getProperty(jdbc.driver);JDBC_URL = properties.getProperty(jdbc.url);JDBC_USER = properties.getProperty(jdbc.user);JDBC_PASS = properties.getProperty(jdbc.pass);讀取的各個配置的作用,將在9.4.3中作詳細講解。9.4.3 編寫JDBC操作類JDBC是Java Data Base
45、Connectivity的簡稱,是Java中進行數(shù)據(jù)庫連接的技術。JDBC的API提供了標準統(tǒng)一的SQL數(shù)據(jù)存取接口,可以讓程序員不需要關心如何去連接不同的數(shù)據(jù)庫,只需為不同的數(shù)據(jù)庫提供不同的驅動,就可以達到連接不同數(shù)據(jù)庫的要求。在9.4.2中,我們已經(jīng)提供了配置,可以修改對應的配置文件來連接數(shù)據(jù)庫,perties文件中的jdbc.driver屬性,就是數(shù)據(jù)庫的連接驅動,在本例中我們使用了MySQL數(shù)據(jù)庫,因此需要提供MySQL的數(shù)據(jù)庫驅動包。本例中使用的驅動包版本為5.1.6,如果需要最新的驅動程序,請到 HYPERLINK xdev.mysqlx/downloads/con
46、nector/j/5.1.html xdev.mysqlx/downloads/connector/j/5.1.html下載,下載后將驅動包加到環(huán)境變量中。除了配置驅動外,還需要配置數(shù)據(jù)庫的連接地址、用戶名和密碼,jdbc.url=jdbc:mysql:/服務器ip:3306/book_system,用戶名密碼為你的MySQL用戶密碼。配置好了之后,我們可以開始著手編寫數(shù)據(jù)庫的操作類,但在那之前,我們需要明確這個類幫我做些什么。首先肯定是幫我們進行數(shù)據(jù)庫連接,我們之前配置了連接的相關屬性,但是程序并不知道我們需要怎樣去連接,接著我們需要這個類幫我們提供查詢、執(zhí)行SQL等功能。確定好目標后,開始
47、編寫。新建JDBCExecutor類,該類具有屬性如下:private static String DRIVER = PropertiesUtil.JDBC_DRIVER;/獲得驅動private static String URL = PropertiesUtil.JDBC_URL;/獲得urlprivate static String USER = PropertiesUtil.JDBC_USER;/獲得連接數(shù)據(jù)庫的用戶名private static String PASS = PropertiesUtil.JDBC_PASS;/獲得連接數(shù)據(jù)庫的密碼private Connection c
48、onnection;/連接對象private static JDBCExecutor jdbcExecutor;/維護一個本類型的對象private Statement stmt;/維護一個本類型的對象注:以上代碼的黑體部分,由于創(chuàng)建一個Connection對象需要耗費很大的資源,因此我們使用單態(tài)模式,讓JDBCExecutor類維護一個JDBCExecutor對象,可以在構造器中創(chuàng)建Connection,由于JDBCExecutor是單態(tài)的,因此可以保證在應用中只創(chuàng)建一個Connection,單態(tài)模式將在下一小節(jié)中詳細講述。下面在JDBCExecutor的構造器中創(chuàng)建各個對象,再提供一個方法
49、返回JDBCExecutor的實例。代碼清單:codebooksrcorgcrazyitbookjdbcJDBCExecutor.java/私有構造器private JDBCExecutor() /初始化JDBC驅動并讓驅動加載到jvm中Class.forName(DRIVER);/創(chuàng)建數(shù)據(jù)庫連接connection = DriverManager.getConnection(URL, USER, PASS);/創(chuàng)建Statement對象stmt = connection.createStatement();/提供一個靜態(tài)方法返回本類的實例public static JDBCExecutor
50、getJDBCExecutor() /如果本類所維護jdbcExecutor屬性為空,則調(diào)用私有的構造器獲得實例if (jdbcExecutor = null) jdbcExecutor = new JDBCExecutor();return jdbcExecutor;注:在以上代碼中,提供了一個JDBCExecutor的私有構造器,因為需要保持這個類只創(chuàng)建一次,因此不可提供public的構造器讓其他類去創(chuàng)建JDBCExecutor的實例,外界只能通過它自己內(nèi)部的一個靜態(tài)方法創(chuàng)建JDBCExecutor實例。編寫執(zhí)行查詢的方法,代碼清單:codebooksrcorgcrazyitbookjdb
51、cJDBCExecutor.java/執(zhí)行一句查詢的sql, 并返回ResultSet對象public ResultSet executeQuery(String sql) /利用Statement對象執(zhí)行參數(shù)的sqlResultSet result = stmt.executeQuery(sql);return result;在上面的代碼中,并沒有關閉ResultSet的代碼,直接返回ResultSet對象,我們還需要對ResultSet對象進行一些處理,因此在這里不進行關閉操作,該方法只是簡單的進行查詢。編寫執(zhí)行SQL的方法,代碼清單:codebooksrcorgcrazyitbookjd
52、bcJDBCExecutor.java/執(zhí)行單句INSERT、UPDATE 或 DELETE 語句, 如果執(zhí)行INSERT時, 返回主鍵public int executeUpdate(String sql) int result = -1;/執(zhí)行SQL語句stmt.executeUpdate(sql);/獲得主鍵ResultSet rs = stmt.getGeneratedKeys();while(rs.next() result = rs.getInt(1);/返回最后一個主鍵rs.close();return result;在以上代碼中,將會返回執(zhí)行該句SQL所產(chǎn)生的主鍵。到這里,我們
53、的JDBCExecutor類已經(jīng)編寫完了。9.4.4創(chuàng)建數(shù)據(jù)轉換工具類在9.4.3中,JDBCExecutor中提供了一個executeQuery方法,該方法返回ResultSet對象,當時我們并沒有關閉ResultSet,這是由于我們需要對該結果集進行一些封裝。在本小節(jié)中將建立一個工具類,進該結果集進行封裝,并返回對應的集合。在9.4.1中,我們設計了各個表所對應的類,那么在封裝的過程中,將結果集(ResultSet)中的某個值作為這些類(表對象)的屬性,并負責創(chuàng)建這些對象,放到集合中去。新建DataUtil類,具體的代碼如下。代碼清單:codebooksrcorgcrazyitbookco
54、mmonsDataUtil.java/將rs中的值封裝成一個集合public static Collection getDatas(Collection result, ResultSet rs, Class clazz) while (rs.next() /創(chuàng)建類的實例Object vo = clazz.newInstance();/獲取本對象的屬性Field fields = clazz.getDeclaredFields();/獲取父類的屬性Field superFields = clazz.getSuperclass().getDeclaredFields();/父類的屬性和自己的屬性
55、相加Field allFields = addFields(superFields, fields);/遍歷所有的屬性for (Field field : allFields) /獲得setter方法的方法名String setterMethodName = getSetterMethodName(field.getName();/獲得setter方法Method setterMethod = clazz.getMethod(setterMethodName, field.getType();invokeMethod(rs, field, vo, setterMethod);result.ad
56、d(vo);rs.close();return result;/執(zhí)行一個方法, 從ResultSet中獲取一個字段的數(shù)據(jù), 調(diào)用vo的setter方法private static void invokeMethod(ResultSet rs, Field field, Object vo, Method setterMethod) /當使用ResultSet獲取某個字段的時候, 如果沒有該字段, 會出現(xiàn)SQLException, 在這里忽略該異常String value = rs.getString(field.getName();/從ResultSet中獲取與該對象屬性名一致的字段, 并執(zhí)行
57、setter方法setterMethod.invoke(vo, value);/根據(jù)屬性名獲得setter方法的方法名private static String getSetterMethodName(String fieldName) String begin = fieldName.substring(0, 1).toUpperCase();String end = fieldName.substring(1, fieldName.length();String methodName = set + begin + end;return methodName;/相加兩個數(shù)組private
58、static Field addFields(Field f1, Field f2) List l = new ArrayList();for (Field f : f1) l.add(f);for (Field f : f2) l.add(f);return l.toArray(new Fieldf1.length + f2.length);注意以上代碼的黑體部分,先使用class的newInstance方法創(chuàng)建類的實例,再獲得父類和本類的屬性,再通過setter方法將ResultSet中對應的值設置到對象中。我們在9.4.1中,約定了各個類的屬性命名都需要與數(shù)據(jù)庫中的表字段一致,在這里,我
59、們很容易就可以得到某個字段的setter方法,并可以根據(jù)類的屬性名稱得到ResultSet中對應的字段值。在本例中,父類就是ValueObject,ValueObject中有一個ID屬性,就對應了各個表中的ID字段。ValueObject下面的各個子類的class都可以作為getDatas的clazz參數(shù)傳入,從而創(chuàng)建傳入類的對象。簡單的說,DataUtil就是根據(jù)ResultSet來創(chuàng)建ValueObject的集合,當創(chuàng)建完后,就需要在這里關閉ResultSet對象。這也是為什么在JDBCExecutor不需要關閉ResultSet的原因。到這里,開發(fā)的準備工作已經(jīng)全部完成了,在本小節(jié)中,描
60、述了如何連接JDBC進行數(shù)據(jù)庫連接,使用Java的反射進行字段與類屬性的映射,這些都為我們后面的功能開發(fā)打好了基礎,在開發(fā)的過程中,我們可以直接編寫SQL,得到結果集,傳遞給DataUtil類,讓它轉換成集合,我們不再需要去處理ResultSet、Connection和Statement等對象。9.5 出版社管理功能從本小節(jié)開始,我們開始實現(xiàn)系統(tǒng)功能,從最簡單的出版社管理功能開始,由于出版社表中不涉及任何的外鍵,界面中只有一個簡單的列表和表單,實現(xiàn)起來比較簡單。9.5.1 分層結構我們可以將系統(tǒng)分為三層:表現(xiàn)層、業(yè)務層、數(shù)據(jù)訪問層,這樣分層的好處在于,如果視圖層發(fā)生變化,例如不再使用swing
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 人教版高中數(shù)學必修⑤2.2《等差數(shù)列》教學設計
- 安全環(huán)保主題演講稿(集合9篇)
- 組長崗位說明書
- 海南三沙圖書館招聘試題帶答案分析2024年
- 2024年陜西省大學生到政府機關考試真題
- 高教版中職數(shù)學拓展模塊一下冊8.1.3 計數(shù)原理的應用課件
- 建筑公司施工用電三級配電執(zhí)行規(guī)定
- YOLOv8與DIDSON技術在水域漁業(yè)資源動態(tài)監(jiān)測中的應用研究
- 建筑公司鋼筋綁扎驗收流程規(guī)范制度
- 體教結合視角下“家校社”協(xié)同促進兒童體質健康的策略研究
- 語文學科核心素養(yǎng)
- TYCST 004-2024 透水水泥穩(wěn)定碎石基層 透水系數(shù)的測定
- 部門級安全培訓試題加解析答案可打印
- 廣西版五年級下冊美術全冊教案【完整版】
- 2024年清理道路塌方協(xié)議書模板
- 車間6S可視化管理之定置劃線標準解讀
- GB/T 24067-2024溫室氣體產(chǎn)品碳足跡量化要求和指南
- GB 44495-2024汽車整車信息安全技術要求
- Odoo:Odoo集成與第三方應用技術教程.Tex.header
- 人教版五年級3《長方體和正方體》 單元整體作業(yè)設計
- 機械設備賠償協(xié)議
評論
0/150
提交評論