




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、PAGE 222Eclipse從入門(mén)到精通PAGE 101第9章 圖書(shū)進(jìn)存銷系統(tǒng)第9章 圖書(shū)進(jìn)存銷系統(tǒng)第9章圖書(shū)進(jìn)存銷系統(tǒng)9.1 項(xiàng)目簡(jiǎn)介本章介紹如何開(kāi)發(fā)一個(gè)CS結(jié)構(gòu)的圖書(shū)進(jìn)存銷系統(tǒng),該系統(tǒng)的主要有出版社管理、書(shū)本管理、書(shū)的入庫(kù)管理、銷售管理等功能,通過(guò)這些簡(jiǎn)單的功能,可以讓我們了解如何利用JDBC進(jìn)行數(shù)據(jù)庫(kù)操作、如何使用Java的反射機(jī)制以及如何對(duì)系統(tǒng)進(jìn)行分層等知識(shí)點(diǎn)。9.2建立界面在實(shí)現(xiàn)功能前,我們需要為這個(gè)系統(tǒng)建立界面和設(shè)計(jì)數(shù)據(jù)庫(kù),本小節(jié)將建立在這個(gè)小系統(tǒng)中所需要的各個(gè)界面。9.2.1登錄界面在進(jìn)入系統(tǒng)前,我們需要經(jīng)過(guò)簡(jiǎn)單的認(rèn)證才能進(jìn)入,因此需要提供一個(gè)簡(jiǎn)單的登錄界面,當(dāng)輸入用戶名和密碼
2、都正確時(shí),就可以進(jìn)入系統(tǒng)。需要建立的登錄界面如圖9.1所示。圖9.1 登錄界面界面非常的簡(jiǎn)單,只是兩個(gè)輸入框,一個(gè)按鈕即可實(shí)現(xiàn)。帳號(hào)輸入框使用的是JTextField類,而密碼輸入框使用的是JPasswordField類,使用JPasswordField對(duì)象并不會(huì)顯示原始輸入的字符。在本章中,我們將在最后再去實(shí)現(xiàn)用戶的登錄,先去實(shí)現(xiàn)系統(tǒng)的銷售和入庫(kù)功能。9.2.2 銷售管理界面銷售管理界面主要用于進(jìn)行書(shū)的銷售操作,添加一本需要交易的書(shū)、從交易列表中移除該書(shū)、進(jìn)行交易等操作,在本界面的上半部分為交易記錄列表,我們約定交易記錄列表所顯示的為今天進(jìn)行的交易,并提供一個(gè)輸入日期的輸入框,可以根據(jù)日期進(jìn)
3、行查詢?cè)撎斓慕灰子涗?。本界面的下半部分為顯示某筆交易的具體信息,包括該筆交易所涉及的金額、銷售量、交易日期、交易所涉及的書(shū)等信息。初步的界面如圖9.2所示。圖9.2 銷售界面如圖9.2,銷售管理界面的交易記錄列表中,每列的字段分別為該交易所涉及的書(shū)本名、總價(jià)、交易日期、總數(shù)量。銷售管理界面的下面部分,是顯示具體某筆交易的界面,顯示對(duì)應(yīng)某筆交易的總價(jià)、交易日期、總數(shù)量、交易涉及書(shū)的列表,其中交易中涉及書(shū)的列表中,包括書(shū)的書(shū)名、單價(jià)、和本次交易中該本書(shū)出售的數(shù)量。交易中涉及的書(shū)列表下,可以選擇書(shū)和輸入書(shū)的數(shù)量,并提供添加和刪除按鈕,當(dāng)選擇了一本書(shū)并輸入相應(yīng)的交易數(shù)量,再點(diǎn)擊添加時(shí),即可向交易涉及的
4、書(shū)列表中添加書(shū)的記錄,當(dāng)然也可以進(jìn)行刪除操作。在界面的最上面,有一個(gè)查詢按鍵,可以輸入日期進(jìn)行交易記錄查詢。注:具體某筆交易的界面(界面的下面部分),總價(jià)、交易日期和總數(shù)量是不可輸入的,這是由于總價(jià)是由各本書(shū)的單價(jià)乘以交易數(shù)量得出來(lái)的,交易日期是當(dāng)前交易時(shí)系統(tǒng)的時(shí)間為準(zhǔn)的,總數(shù)量是各本書(shū)的交易數(shù)量總和,因此并不需要人手進(jìn)行輸入。另外,如果在書(shū)本的下拉框中選擇了某本書(shū)時(shí),將會(huì)帶出該本書(shū)的單介和庫(kù)存,好讓使用者在操作時(shí)對(duì)該本書(shū)的狀況有所了解。在本例中,每一個(gè)界面對(duì)應(yīng)一個(gè)JPanel,每個(gè)界面都是一個(gè)JPanel類的子類,銷售管理界面里面是一個(gè)JSplitPane對(duì)象,上面放一個(gè)個(gè)JScrollPa
5、ne對(duì)象,下面部分也是一個(gè)JScrollPane對(duì)象。上面的JScrollPane對(duì)象主要存放一個(gè)JTable,下面的JScrollPane主要放一些Box對(duì)象進(jìn)行布局,詳細(xì)請(qǐng)看圖書(shū)進(jìn)存銷系統(tǒng)代碼清單中的SalePanel類。9.2.3入庫(kù)管理界面入庫(kù)管理界面和銷售管理界面的布局大致相同,只是其中的數(shù)據(jù)列和文字有所差距。入加管理界面如圖9.3所示。圖9.3 庫(kù)存管理界面與銷售管理界面類似,上面的列表是入庫(kù)記錄,一條入庫(kù)記錄包括入庫(kù)時(shí)所涉及的書(shū)本、入庫(kù)日期和入庫(kù)書(shū)本的總數(shù)量。界面下面部分是具體某條入庫(kù)記錄的具體信息,包括入庫(kù)日期、總數(shù)量和入庫(kù)書(shū)本的列表,同樣地,入庫(kù)日期與總數(shù)量都不可以手動(dòng)輸入。
6、在新增一條入庫(kù)記錄時(shí),可以向書(shū)本列表添加和刪除書(shū)本,表示該入庫(kù)記錄中所涉及的書(shū)本及對(duì)應(yīng)的數(shù)量。注:在選擇某本書(shū)時(shí),需要自動(dòng)帶出該書(shū)的庫(kù)存。在本例中,入庫(kù)管理界面對(duì)應(yīng)的類為RepertoryPanel類,是JPanel的子類。9.2.4 書(shū)本管理界面書(shū)本管理界面主要包括書(shū)本的查詢、列表、查看等功能,書(shū)本在本例中作為基礎(chǔ)數(shù)據(jù)的角色,主要用于銷售和入庫(kù)。這里需要注意的是,在新增一本書(shū)的時(shí)候,該書(shū)的庫(kù)存為0,只有經(jīng)過(guò)銷售和入庫(kù)才會(huì)對(duì)書(shū)的庫(kù)存量產(chǎn)生影響。書(shū)的基本信息除了書(shū)名、價(jià)格介紹、所屬出版社和書(shū)的種類外,還需要有書(shū)的圖片,為簡(jiǎn)單起見(jiàn),本例中的每本書(shū)只有一張圖片,因此不需要另外建立表來(lái)存放書(shū)的圖片。書(shū)
7、本管理界面如圖9.4所示。圖9.4 書(shū)本管理界面書(shū)本管理界面上面的列表主要顯示書(shū)本名稱、簡(jiǎn)介、所屬種類、出版社、庫(kù)存數(shù)量和價(jià)格這些信息,此處的書(shū)本名稱與銷售管理(入庫(kù)管理)界面中的書(shū)本名稱有所區(qū)別,這里的書(shū)本名稱的列寬較窄,這是由于銷售(入庫(kù))中所涉及的是多本書(shū),而書(shū)本管理界面中每一條書(shū)的記錄只是代表一本書(shū)。在界面的下方有一個(gè)表單,用于查看、修改和添加書(shū)本操作,表單的右邊是書(shū)的圖片顯示區(qū),用于顯示書(shū)本所對(duì)應(yīng)的縮略圖,當(dāng)用戶點(diǎn)擊縮略圖的時(shí)候,可以彈出新的窗口用于展示大圖。與前面的界面一樣,在程序中,我們新增一個(gè)BookPanel作為該界面。9.2.5 種類管理界面書(shū)的種類,表示一本書(shū)是屬于哪個(gè)種
8、類的,例如計(jì)算機(jī)、文學(xué)、法律等等,這些都是書(shū)的種類,我們提供一個(gè)種類管理界面,可以用于管理各個(gè)種類。種類在本例中與書(shū)本一樣,屬于基礎(chǔ)數(shù)據(jù)。新增種類并不需要任何約束,只需要輸入種類的名稱即可。在書(shū)的管理界面中,如果需要添加一本書(shū),必須選擇該書(shū)所對(duì)應(yīng)的種類。種類管理界面如圖9.5所示。圖9.5 種類管理界面如圖9.5所示,種類管理界面并不復(fù)雜,上面是一個(gè)簡(jiǎn)單的列表,下面是普通的查看、新增與修改的表單。在程序中,我們新增一個(gè)TypePanel作為該界面。9.2.6 出版社管理界面添加一本書(shū),除了需要有種類之外,還需要選擇該書(shū)的出版社,我們提供一個(gè)出版社管理界面。如圖9.6所示。圖9.6 出版社管理界
9、面出版社列表中,主要顯示出版社名稱、聯(lián)系人、x和簡(jiǎn)介這些信息,下面的表單與前面幾個(gè)界面的表單類似,都是用于查看、修改和新增。在程序中,我們新增一個(gè)ConcernPanel來(lái)表示這個(gè)界面。從9.2.2到9.2.6的各個(gè)系統(tǒng)界面,都是存在于一個(gè)JFrame中,我們可以提供菜單,當(dāng)點(diǎn)擊了某個(gè)菜單的時(shí)候,JFrame中的各個(gè)JPanel對(duì)象隱藏,只顯示對(duì)應(yīng)的那個(gè)JPanel。到此,我們所需要的界面已經(jīng)全部完成了,在9.2.7中我們將對(duì)各個(gè)界面的代碼進(jìn)行優(yōu)化,再去為主界面加上相應(yīng)的菜單,我們的界面就全部完成。9.2.7 修改界面代碼本例中涉及的各個(gè)界面,我們可以發(fā)現(xiàn)界面幾乎都大同小異,界面上面部分是一個(gè)
10、列表,下面是一個(gè)表單,因此,我們可以將這幾個(gè)界面的共同部分提取出來(lái),作為每個(gè)界面對(duì)象(JPanel)的父類,將一些可以重用的代碼提升至父類,并可以使用“模板方法”,提供一些抽象的方法讓各個(gè)子類去實(shí)現(xiàn)。以下代碼為各個(gè)界面對(duì)象的父類(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ù)設(shè)置進(jìn)JTable中public void initData() if (this.table = null) return; DefaultTableModel tableModel = (DefaultTableModel)this.table.getModel();/將數(shù)據(jù)設(shè)入表格Model中tableModel.setDa
12、taVector(getDatas(), getColumns();/設(shè)置表格樣式setTableFace();/刷新列表的方法public void refreshTable() initData();getJTable().repaint();/獲取表列集合, 由子類去實(shí)現(xiàn)public abstract Vector getColumns();/設(shè)置列表的樣式, 由子類去實(shí)現(xiàn)public abstract void setTableFace();/設(shè)置數(shù)據(jù)列表的方法,由子類去實(shí)現(xiàn)public abstract void setViewDatas();/清空界面下邊的列表public abs
13、tract void clear();/給子類使用的方法, 用于獲取一個(gè)列表的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;以上的代碼,提供一個(gè)JTable的屬性,這是因?yàn)槊總€(gè)界面中都有一個(gè)主要的列表對(duì)象,例如銷售管理界面中的銷售記錄列表、書(shū)本管理界面中的書(shū)本列表等。注意代
14、碼中的黑體部分,都是由子類去實(shí)現(xiàn)的方法,getColumns()由子類去提供列表的列集合;setTableFace()是由子類去設(shè)置JTable的顯示,例如需要設(shè)置某一列的寬度或者設(shè)置列表的行高等等;而setViewDatas()方法是重新去數(shù)據(jù)庫(kù)讀取數(shù)據(jù),由子類去實(shí)現(xiàn);clear()方法是刷新每個(gè)界面下邊的表單,同樣由子類去實(shí)現(xiàn)。在CommonPanel中提供了一個(gè)getSelectId方法,用來(lái)獲得JTable屬性中所選中的某一行中id列的值,也就是意味著在列表中,必須要有一個(gè)列名叫做id的列。父類定義好規(guī)范之后,子類就可以根據(jù)不同的情況,給父類不同的列,讓父類進(jìn)行顯示,除了需要提供列的集
15、合外,還需要提供數(shù)據(jù),也就是CommonPanel中的datas屬性。我們這里提供了一個(gè)setViewDatas的方法,主要從數(shù)據(jù)庫(kù)中讀取相關(guān)的數(shù)據(jù),再調(diào)用父類的initDatas方法構(gòu)建列表。那么存放各個(gè)界面對(duì)象的JFrame類中,可以提供一個(gè)方法,當(dāng)界面發(fā)生轉(zhuǎn)換時(shí),就調(diào)用setViewDatas方法,具體代碼如下。代碼清單:codebooksrcorgcrazyitbookuiMainFrame.java/切換各個(gè)界面private void changePanel(CommonPanel commonPanel) /移除當(dāng)前顯示的JPanelthis.remove(currentPane
16、l);/添加需要顯示的JPanelthis.add(commonPanel);/設(shè)置當(dāng)前的JPanelthis.currentPanel = commonPanel;this.repaint();this.setVisible(true);/調(diào)用CommonPanel的方法重新讀取數(shù)據(jù)并刷新列表commonPanel.setViewDatas ();/清空界面下邊的表單commonPanel.clear();以上代碼的黑體部分,調(diào)各個(gè)界面對(duì)象父類的setVieweDatas方法重新讀取數(shù)據(jù)并刷新列表,各個(gè)界面中轉(zhuǎn)換時(shí),當(dāng)點(diǎn)擊了對(duì)應(yīng)的菜單后,再進(jìn)行轉(zhuǎn)換(調(diào)用changePanel方法)。代碼清單
17、:codebooksrcorgcrazyitbookuiMainFrame.javaprivate Action sale = new AbstractAction(銷售管理, new ImageIcon(images/sale.gif) public void actionPerformed(ActionEvent e) /調(diào)用轉(zhuǎn)換的方法changePanel(salePanel);以上代碼表示點(diǎn)擊了銷售管理的菜單后,就調(diào)用changePanel方法,轉(zhuǎn)換界面并初始化數(shù)據(jù)。另外,每個(gè)界面的主列表我們使用一個(gè)CommonJTable對(duì)象,該對(duì)象繼承于JTable,我們并不需要讓列表的每個(gè)單元格
18、可以編輯,因此重寫(xiě)JTable的isCellEditable方法即可,代碼如下。代碼清單:codebooksrcorgcrazyitbookuiCommonJTable.javapublic class CommonJTable extends JTable public CommonJTable(TableModel dm) super(dm);/設(shè)置表格只能選擇一行g(shù)etSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); /重寫(xiě)父類的方法, 使所有的單元格不可編輯public boolean isC
19、ellEditable(int row, int column) return false;做了以上的準(zhǔn)備工作后,就可以修改各個(gè)界面對(duì)應(yīng)的類,去繼承CommonPanel即可,實(shí)現(xiàn)getColumns()、setTableFace()、setViewDatas()和clear()方法,而數(shù)據(jù)暫時(shí)不必提供,下一節(jié)我們將開(kāi)始設(shè)計(jì)數(shù)據(jù)庫(kù)。9.3 設(shè)計(jì)系統(tǒng)數(shù)據(jù)庫(kù)在9.2中我們已經(jīng)建立了系統(tǒng)的相關(guān)界面,接下來(lái),這一小節(jié)將設(shè)計(jì)這個(gè)系統(tǒng)的數(shù)據(jù)庫(kù)。本例使用的是MySQL5.0作為數(shù)據(jù)庫(kù)。在設(shè)計(jì)數(shù)據(jù)庫(kù)前,我們可以確定,系統(tǒng)相關(guān)的表,從最基礎(chǔ)開(kāi)始,有出版社表、書(shū)的類型表、書(shū)表、入庫(kù)記錄表和銷售記錄表,其中,一條入
20、庫(kù)記錄中涉及多本書(shū),一條銷售記錄也涉及多本書(shū),因此還需要書(shū)的入庫(kù)記錄表和書(shū)的銷售記錄表,一條書(shū)的入庫(kù)記錄對(duì)應(yīng)一本書(shū),該條書(shū)的入庫(kù)記錄屬于某一條入庫(kù)記錄,可以理解成這是書(shū)與入庫(kù)記錄的關(guān)系表,同樣地,書(shū)的銷售記錄與書(shū)的入庫(kù)記錄一樣。如果上面的文字難以理解,可以看下面的數(shù)據(jù)庫(kù)結(jié)構(gòu),更有助于理解。在設(shè)計(jì)各個(gè)表前,我們需要?jiǎng)?chuàng)建數(shù)據(jù)庫(kù),在MySQL中,創(chuàng)建BOOK_SYSTEM數(shù)據(jù)庫(kù),具體的SQL語(yǔ)句如下:- 創(chuàng)建DATABASECREATE DATABASE IF NOT EXISTS BOOK_SYSTEM;- 使用BOOK_SYSTEMUSE BOOK_SYSTEM;MySQL中的CREATE和US
21、E語(yǔ)法可查看MySQL的幫助文檔。9.3.1 設(shè)計(jì)出版社表在9.2.6中,我們已經(jīng)建立了出版社的管理界面,現(xiàn)在只需要根據(jù)界面來(lái)設(shè)計(jì)數(shù)據(jù)庫(kù)即可。我們?cè)贛ySQL中建立表T_PUBLISHER,出版社表包括的字段有:ID:主鍵ID。PUB_NAME:出版社名稱。PUB_TEL:x。PUB_LINK_MAN:聯(lián)系人。PUB_INTRO:出版社簡(jiǎn)介。由于出版社是最基礎(chǔ)的數(shù)據(jù),因此不需要其他的外鍵關(guān)系。以下為創(chuàng)建T_PUBLISHER這個(gè)表的SQL。- 出版社CREATE TABLE IF NOT EXISTS T_PUBLISHER ( ID int AUTO_INCREMENT NOT NULL,
22、- 主鍵生成策略為自動(dòng)增長(zhǎng) PUB_NAME varchar(50), - 出版社名稱 PUB_TEL varchar(50), - x PUB_LINK_MAN varchar(50), - 聯(lián)系人 PUB_INTRO varchar(200), - 簡(jiǎn)介 PRIMARY KEY (ID) - 聲明主鍵);如果你有MySQL的一些管理工具,可以使用這些工具進(jìn)行創(chuàng)建表,并不需要自己書(shū)寫(xiě)SQL語(yǔ)句,但筆者還是希望能夠自己嘗試去編寫(xiě)這些SQL,因?yàn)閷?duì)于初學(xué)者而言,可以自己去編寫(xiě)這些SQL,無(wú)疑是對(duì)自己能力的一種提高。9.3.2 設(shè)計(jì)種類表種類表與出版社表一樣,并不復(fù)雜,也沒(méi)有任何的外鍵,根據(jù)9.2
23、.5的界面,就可以確定需要哪些字段了。創(chuàng)建T_BOOK_TYPE表,包括以下的字段:ID:主鍵IDTYPE_NAME:種類的名稱。TYPE_INTRO:種類的簡(jiǎn)介。只有簡(jiǎn)單的三個(gè)字段,創(chuàng)建的SQL如下。- 書(shū)種類CREATE TABLE IF NOT EXISTS T_BOOK_TYPE ( ID int AUTO_INCREMENT NOT NULL, - 主鍵生成策略為自動(dòng)增長(zhǎng) TYPE_NAME varchar(50), - 種類名稱 TYPE_INTRO varchar(200), - 種類簡(jiǎn)介 PRIMARY KEY (ID);9.3.3 設(shè)計(jì)書(shū)表在9.2.4的界面中,我們可以看到,
24、一本書(shū)所需要的字段包括:書(shū)名、簡(jiǎn)介、作者、所屬種類、出版社、縮略圖地址、庫(kù)存和價(jià)格,種類表和出版社表已經(jīng)在9.3.2與9.3.1中設(shè)計(jì)了,只需要為書(shū)表添加外鍵關(guān)系即可,新增表T_BOOK,以下為書(shū)表各個(gè)字段的描述:ID:主鍵IDBOOK_NAME:書(shū)的名字。BOOK_INTRO:書(shū)的簡(jiǎn)介。BOOK_PRICE:書(shū)的單價(jià)。TYPE_ID_FK:書(shū)所屬的種類ID外鍵。PUB_ID_FK:出版社外鍵。IMAGE_URL:縮略圖的地址。AUTHOR:作者名稱。REPERTORY_SIZE:庫(kù)存量。這里需要注意一下,書(shū)的名字、簡(jiǎn)價(jià)、單價(jià)、所屬的種類、出版社、縮略圖和作者,都可以在界面中通過(guò)輸入或者選擇寫(xiě)
25、入到數(shù)據(jù)庫(kù)中,但是庫(kù)存量是由銷售與入庫(kù)決定的,因此在修改書(shū)的時(shí)候,不可以設(shè)置書(shū)的庫(kù)存量。創(chuàng)建該表的SQL如下。- 書(shū)CREATE TABLE IF NOT EXISTS T_BOOK ( ID int AUTO_INCREMENT NOT NULL, - ID字段,自增 BOOK_NAME varchar(50), - 書(shū)名稱 BOOK_INTRO varchar(200), - 書(shū)簡(jiǎn)介BOOK_PRICE double, - 書(shū)的單價(jià) 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), - 庫(kù)存數(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 設(shè)計(jì)入庫(kù)記錄表在設(shè)計(jì)入庫(kù)記錄前,我們需要知道的是,一個(gè)入庫(kù)記錄,包含多本書(shū)的入庫(kù),也就是說(shuō),一次入庫(kù),有可能入庫(kù)多本書(shū)。入庫(kù)記錄,只需要記錄入庫(kù)的時(shí)
27、間即可,新建T_IN_RECORD表,該表的字段如下:ID:主鍵ID。RECORD_DATE:入庫(kù)日期。以下為創(chuàng)建該表的SQL。- 入庫(kù)記錄表, 一次入庫(kù)會(huì)入多本書(shū)CREATE TABLE IF NOT EXISTS T_IN_RECORD ( ID int AUTO_INCREMENT NOT NULL, RECORD_DATE datetime, - 入庫(kù)日期 PRIMARY KEY (ID);設(shè)計(jì)完入庫(kù)記錄后,我們還需要考慮,一次入庫(kù)涉及了多本書(shū),因此需要添加一個(gè)關(guān)系表,用來(lái)表示一次入庫(kù)中所涉及的書(shū)。創(chuàng)建T_BOOK_IN_RECORD表,該表的字段如下:ID:該表的主鍵IDBOOK_I
28、D_FK:書(shū)的外鍵,表示這一條書(shū)的入庫(kù)記錄所對(duì)應(yīng)的書(shū)。T_IN_RECORD_ID_FK:入庫(kù)記錄的外鍵,表示這一條書(shū)的入庫(kù)記錄所對(duì)應(yīng)的是哪一次入庫(kù),這個(gè)關(guān)系也表示了一次入庫(kù)可以有多條書(shū)的入庫(kù)記錄。IN_SUM:這一條書(shū)的入庫(kù)記錄中對(duì)應(yīng)的書(shū)的入庫(kù)數(shù)量。創(chuàng)建的SQL語(yǔ)句如下。- 書(shū)的入庫(kù)記錄CREATE TABLE IF NOT EXISTS T_BOOK_IN_RECORD ( ID int AUTO_INCREMENT NOT NULL, - ID自增 BOOK_ID_FK int, - 入庫(kù)的書(shū) T_IN_RECORD_ID_FK int, - 對(duì)應(yīng)的入庫(kù)記錄 IN_SUM int(10)
29、, - 入庫(kù)數(shù)量 FOREIGN KEY (BOOK_ID_FK) REFERENCES T_BOOK (ID), - 聲明書(shū)的外鍵 FOREIGN KEY (T_IN_RECORD_ID_FK) REFERENCES T_IN_RECORD (ID), - 聲明入庫(kù)記錄外鍵 PRIMARY KEY (ID);注:在入庫(kù)表中,并沒(méi)有提供入庫(kù)總數(shù)量這個(gè)字段,這是由于入庫(kù)總數(shù)量是各本書(shū)的入庫(kù)數(shù)量的總和。因此并不需要在數(shù)據(jù)庫(kù)中提供字段,只需要在程序中進(jìn)行計(jì)算即可。創(chuàng)建完了這兩個(gè)表之后,就完成了書(shū)的入庫(kù)相關(guān)表的設(shè)計(jì)。9.3.5 設(shè)計(jì)銷售記錄表銷售記錄表與入庫(kù)記錄表大同小異,都是需要?jiǎng)?chuàng)建一個(gè)銷售表,再創(chuàng)
30、建書(shū)的銷售表。一條銷售記錄對(duì)應(yīng)多條書(shū)的銷售記錄,一次銷售所涉及多本書(shū),與入庫(kù)記錄一樣,都通過(guò)一個(gè)中關(guān)系表來(lái)體現(xiàn)這種關(guān)系。銷售記錄表的字段如下:ID:ID主鍵。RECORD_DATE:交易日期。創(chuàng)建該表的SQL如下。- 交易記錄表, 一個(gè)交易記錄包括多個(gè)書(shū)的銷售記錄, 一次交易可能有多本書(shū)CREATE TABLE IF NOT EXISTS T_SALE_RECORD ( ID int AUTO_INCREMENT NOT NULL, RECORD_DATE datetime,- 交易日期 PRIMARY KEY (ID);創(chuàng)建了交易表后,再去設(shè)計(jì)書(shū)的交易表,具體字段與書(shū)的入庫(kù)記錄表相似:ID:
31、主鍵IDBOOK_ID_FK:該條書(shū)的交易記錄所對(duì)應(yīng)的書(shū)。T_SALE_RECORD_ID_FK:該條書(shū)的交易記錄所對(duì)應(yīng)的交易記錄。TRADE_SUM:該記錄中對(duì)應(yīng)的書(shū)的交易數(shù)量。創(chuàng)建書(shū)的入庫(kù)記錄表的SQL如下。- 書(shū)的銷售記錄, 一條記錄對(duì)應(yīng)一本書(shū)CREATE TABLE IF NOT EXISTS T_BOOK_SALE_RECORD ( ID int AUTO_INCREMENT NOT NULL, BOOK_ID_FK int, - 銷售的書(shū) T_SALE_RECORD_ID_FK int, - 該書(shū)的銷售記錄所對(duì)應(yīng)的交易記錄 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);注:交易表中并沒(méi)有提供交易總價(jià)和交易總數(shù)量這兩個(gè)字段,這是由于這兩個(gè)值是由各本書(shū)的交易量所決定的。到此,數(shù)據(jù)庫(kù)各個(gè)表的結(jié)構(gòu)已經(jīng)設(shè)計(jì)完成了,各個(gè)表的結(jié)構(gòu)都十分簡(jiǎn)單,只有庫(kù)存與銷售兩個(gè)模塊的表相對(duì)復(fù)雜了一點(diǎn)。在下一節(jié)中,我們將講解如何使用Java的反射進(jìn)行對(duì)象與表的映射與使用JDBC進(jìn)行數(shù)據(jù)庫(kù)操作等知識(shí)。9.4 開(kāi)發(fā)前的準(zhǔn)備工作在9.3小節(jié)中,數(shù)
33、據(jù)庫(kù)已經(jīng)設(shè)計(jì)好了,接下來(lái)可以準(zhǔn)備開(kāi)發(fā)的工作了。其實(shí)當(dāng)設(shè)計(jì)好數(shù)據(jù)庫(kù),我們就可以進(jìn)行開(kāi)發(fā),本小節(jié)中所講的開(kāi)發(fā)準(zhǔn)備工作,是指編寫(xiě)一些公用的方法,例如JDBC的基本操作,包括查詢、修改等。將一些可以重用的代碼先編寫(xiě)好,再去進(jìn)行業(yè)務(wù)開(kāi)發(fā),到業(yè)務(wù)開(kāi)發(fā)的時(shí)候,可以事半功倍。9.4.1 設(shè)計(jì)表的對(duì)應(yīng)類在9.3中,已經(jīng)設(shè)計(jì)了系統(tǒng)所需要的各個(gè)表,包括出版社表、書(shū)種類表、書(shū)表等,那么現(xiàn)在,我們需要為這些表建立相應(yīng)的對(duì)象,每一個(gè)表可以對(duì)應(yīng)一個(gè)對(duì)象??梢詾槊總€(gè)表的對(duì)象先建立一個(gè)父類,由于每個(gè)表中都有ID一列,因此我們可以建立一個(gè)父類,提供ID字段。新建各個(gè)表對(duì)應(yīng)對(duì)象的父類ValueObject,ValueObject的
34、代碼如下。代碼清單:codebooksrcorgcrazyitbookvoValueObject.javapublic class ValueObject /ID字段,對(duì)應(yīng)數(shù)據(jù)庫(kù)中的ID列private String ID;/省略setter和getter方法該類只提供了一個(gè)ID字段,并提供setter和getter方法,注意,ID屬性必須與數(shù)據(jù)庫(kù)中表的ID列名字對(duì)應(yīng),由于這個(gè)是各個(gè)表對(duì)象的父類,因此需要約定每個(gè)表的主鍵命名必須為ID,為什么需要這樣,在下面章節(jié)將會(huì)詳細(xì)講述。建立了父類ValueObject后,此時(shí)再去新建出版社所對(duì)應(yīng)的實(shí)體Concern類,一個(gè)Concern對(duì)象代表一個(gè)出版社
35、,該類繼承于ValueObject,此外,出版社表中有的字段,都需要在這個(gè)類中反應(yīng)出來(lái)。Concern類代碼如下。代碼清單:codebooksrcorgcrazyitbookvoConcern.javapublic class Concern extends ValueObject /出版社名稱private String PUB_NAME;/出版社電話private String PUB_TEL;/聯(lián)系人private String PUB_LINK_MAN;/簡(jiǎn)介private String PUB_INTRO;/省略各個(gè)屬性的getter和setter方法注意各個(gè)屬性的命名,必須要與數(shù)據(jù)
36、庫(kù)中表的字段一致,由于繼承了ValueObject類,因此不需要提供ID字段。按照建立Concern對(duì)象的方法,再去建立Type對(duì)象、Book對(duì)象,Type代表書(shū)本類,Book代表書(shū)類型。在Book類中需要注意的是,由于書(shū)表中有兩個(gè)鍵,分別是種類的外鍵TYPE_ID_FK和出版社的外鍵PUB_ID_FK,同樣地也提供這兩個(gè)類屬性,并不是提供種類的對(duì)象(Type)和出版社的對(duì)象(Concern),另外所有屬性類型都需要為String。Type的代碼如下,代碼清單:codebooksrcorgcrazyitbookvoType.javapublic class Type extends Value
37、Object /名稱private String TYPE_NAME;/簡(jiǎn)介private String TYPE_INTRO;/省略setter和getter方法Book的代碼如下,代碼清單:codebooksrcorgcrazyitbookvoBook.javapublic class Book extends ValueObject private String BOOK_NAME;/書(shū)本名稱private String BOOK_INTRO;/簡(jiǎn)介private String BOOK_PRICE;/書(shū)的單價(jià)private String TYPE_ID_FK;/種類外鍵private
38、String PUB_ID_FK;/出版社外鍵private String REPERTORY_SIZE;/存儲(chǔ)量private String IMAGE_URL;/圖片url創(chuàng)建完三個(gè)基礎(chǔ)數(shù)據(jù)表所對(duì)應(yīng)的類后,接下來(lái)再去創(chuàng)建入庫(kù)記錄表對(duì)應(yīng)的類、書(shū)的入庫(kù)記錄表對(duì)應(yīng)的類、銷售記錄表對(duì)應(yīng)的類和書(shū)的銷售記錄表對(duì)應(yīng)的類。入庫(kù)記錄類InRecord,代碼清單:codebooksrcorgcrazyitbookvoInRecord.javapublic class InRecord extends ValueObject private String RECORD_DATE;/入庫(kù)日期/省略getter和s
39、etter方法書(shū)的入庫(kù)記錄類BookInRecord,代碼清單:codebooksrcorgcrazyitbookvoBookInRecord.javapublic class BookInRecord extends ValueObject private String BOOK_ID_FK;/對(duì)應(yīng)書(shū)的外鍵, 從數(shù)據(jù)庫(kù)查出來(lái)時(shí)有值private String T_IN_RECORD_ID_FK;/對(duì)應(yīng)銷售記錄外鍵private String IN_SUM;/入庫(kù)數(shù)量/省略setter和getter方法銷售記錄類SaleRecord,代碼清單:codebooksrcorgcrazyitbook
40、voSaleRecord.javapublic class SaleRecord extends ValueObject private String RECORD_DATE;/交易日期/省略setter和getter方法書(shū)的銷售記錄類BookSaleRecord。代碼清單:codebooksrcorgcrazyitbookvoBookSaleRecord.javapublic class BookSaleRecord extends ValueObject private String BOOK_ID_FK;/該記錄對(duì)應(yīng)的書(shū)的外鍵private String T_SALE_RECORD_ID
41、_FK;/該記錄對(duì)應(yīng)的銷售記錄的外鍵private String TRADE_SUM;/該記錄所對(duì)應(yīng)的書(shū)的銷售數(shù)量/省略setter和getter方法到現(xiàn)在,與系統(tǒng)相關(guān)的各個(gè)表所對(duì)應(yīng)的類都已經(jīng)編寫(xiě)好了,下面小節(jié),我們將講解這些建立好的類在開(kāi)發(fā)過(guò)程中所體現(xiàn)的作用。9.4.2 編寫(xiě)配置讀取類由于本章涉及到數(shù)據(jù)庫(kù)操作,因此與數(shù)據(jù)庫(kù)相關(guān)的一些配置,例如對(duì)應(yīng)數(shù)據(jù)庫(kù)的相關(guān)驅(qū)動(dòng)、數(shù)據(jù)庫(kù)地址、用戶名和密碼,我們可以放到配置文件中,如果需要更換數(shù)據(jù)庫(kù)或者地址,只需要修改這份配置文件即可。建立配置文件perties,內(nèi)容如下:/JDBC驅(qū)動(dòng)jdbc.driver=com.mysql.jdbc.Dr
42、iver/連接地址jdbc.url=jdbc:mysql:/localhost:3306/book_system/數(shù)據(jù)庫(kù)用戶名jdbc.user=book/密碼jdbc.pass=book建立好該文件后,再編寫(xiě)類去讀取該文件,獲得所需要的值即可。用于讀取配置的PropertiesUtil類,代碼如下。代碼清單:codebooksrcorgcrazyitbookjdbcPropertiesUtil.javapublic class PropertiesUtil private static Properties properties = new Properties();/該記錄所對(duì)應(yīng)的書(shū)的銷售
43、數(shù)量private static String CONFIG = /cfg/perties;/配置文件的路徑/讀取資源文件, 設(shè)置輸入流private static InputStream is = PropertiesUtil.class.getResourceAsStream(CONFIG);public static String JDBC_DRIVER;/數(shù)據(jù)庫(kù)驅(qū)動(dòng)public static String JDBC_URL;/jdbc連接urlpublic static String JDBC_USER;/數(shù)據(jù)庫(kù)用戶名public static String JDBC_
44、PASS;/數(shù)據(jù)庫(kù)密碼static properties.load(is);/加載輸入流/獲得配置的各個(gè)屬性JDBC_DRIVER = properties.getProperty(jdbc.driver);JDBC_URL = properties.getProperty(jdbc.url);JDBC_USER = properties.getProperty(jdbc.user);JDBC_PASS = properties.getProperty(jdbc.pass);讀取的各個(gè)配置的作用,將在9.4.3中作詳細(xì)講解。9.4.3 編寫(xiě)JDBC操作類JDBC是Java Data Base
45、Connectivity的簡(jiǎn)稱,是Java中進(jìn)行數(shù)據(jù)庫(kù)連接的技術(shù)。JDBC的API提供了標(biāo)準(zhǔn)統(tǒng)一的SQL數(shù)據(jù)存取接口,可以讓程序員不需要關(guān)心如何去連接不同的數(shù)據(jù)庫(kù),只需為不同的數(shù)據(jù)庫(kù)提供不同的驅(qū)動(dòng),就可以達(dá)到連接不同數(shù)據(jù)庫(kù)的要求。在9.4.2中,我們已經(jīng)提供了配置,可以修改對(duì)應(yīng)的配置文件來(lái)連接數(shù)據(jù)庫(kù),perties文件中的jdbc.driver屬性,就是數(shù)據(jù)庫(kù)的連接驅(qū)動(dòng),在本例中我們使用了MySQL數(shù)據(jù)庫(kù),因此需要提供MySQL的數(shù)據(jù)庫(kù)驅(qū)動(dòng)包。本例中使用的驅(qū)動(dòng)包版本為5.1.6,如果需要最新的驅(qū)動(dòng)程序,請(qǐng)到 HYPERLINK xdev.mysqlx/downloads/con
46、nector/j/5.1.html xdev.mysqlx/downloads/connector/j/5.1.html下載,下載后將驅(qū)動(dòng)包加到環(huán)境變量中。除了配置驅(qū)動(dòng)外,還需要配置數(shù)據(jù)庫(kù)的連接地址、用戶名和密碼,jdbc.url=jdbc:mysql:/服務(wù)器ip:3306/book_system,用戶名密碼為你的MySQL用戶密碼。配置好了之后,我們可以開(kāi)始著手編寫(xiě)數(shù)據(jù)庫(kù)的操作類,但在那之前,我們需要明確這個(gè)類幫我做些什么。首先肯定是幫我們進(jìn)行數(shù)據(jù)庫(kù)連接,我們之前配置了連接的相關(guān)屬性,但是程序并不知道我們需要怎樣去連接,接著我們需要這個(gè)類幫我們提供查詢、執(zhí)行SQL等功能。確定好目標(biāo)后,開(kāi)始
47、編寫(xiě)。新建JDBCExecutor類,該類具有屬性如下:private static String DRIVER = PropertiesUtil.JDBC_DRIVER;/獲得驅(qū)動(dòng)private static String URL = PropertiesUtil.JDBC_URL;/獲得urlprivate static String USER = PropertiesUtil.JDBC_USER;/獲得連接數(shù)據(jù)庫(kù)的用戶名private static String PASS = PropertiesUtil.JDBC_PASS;/獲得連接數(shù)據(jù)庫(kù)的密碼private Connection c
48、onnection;/連接對(duì)象private static JDBCExecutor jdbcExecutor;/維護(hù)一個(gè)本類型的對(duì)象private Statement stmt;/維護(hù)一個(gè)本類型的對(duì)象注:以上代碼的黑體部分,由于創(chuàng)建一個(gè)Connection對(duì)象需要耗費(fèi)很大的資源,因此我們使用單態(tài)模式,讓JDBCExecutor類維護(hù)一個(gè)JDBCExecutor對(duì)象,可以在構(gòu)造器中創(chuàng)建Connection,由于JDBCExecutor是單態(tài)的,因此可以保證在應(yīng)用中只創(chuàng)建一個(gè)Connection,單態(tài)模式將在下一小節(jié)中詳細(xì)講述。下面在JDBCExecutor的構(gòu)造器中創(chuàng)建各個(gè)對(duì)象,再提供一個(gè)方法
49、返回JDBCExecutor的實(shí)例。代碼清單:codebooksrcorgcrazyitbookjdbcJDBCExecutor.java/私有構(gòu)造器private JDBCExecutor() /初始化JDBC驅(qū)動(dòng)并讓驅(qū)動(dòng)加載到j(luò)vm中Class.forName(DRIVER);/創(chuàng)建數(shù)據(jù)庫(kù)連接connection = DriverManager.getConnection(URL, USER, PASS);/創(chuàng)建Statement對(duì)象stmt = connection.createStatement();/提供一個(gè)靜態(tài)方法返回本類的實(shí)例public static JDBCExecutor
50、getJDBCExecutor() /如果本類所維護(hù)jdbcExecutor屬性為空,則調(diào)用私有的構(gòu)造器獲得實(shí)例if (jdbcExecutor = null) jdbcExecutor = new JDBCExecutor();return jdbcExecutor;注:在以上代碼中,提供了一個(gè)JDBCExecutor的私有構(gòu)造器,因?yàn)樾枰3诌@個(gè)類只創(chuàng)建一次,因此不可提供public的構(gòu)造器讓其他類去創(chuàng)建JDBCExecutor的實(shí)例,外界只能通過(guò)它自己內(nèi)部的一個(gè)靜態(tài)方法創(chuàng)建JDBCExecutor實(shí)例。編寫(xiě)執(zhí)行查詢的方法,代碼清單:codebooksrcorgcrazyitbookjdb
51、cJDBCExecutor.java/執(zhí)行一句查詢的sql, 并返回ResultSet對(duì)象public ResultSet executeQuery(String sql) /利用Statement對(duì)象執(zhí)行參數(shù)的sqlResultSet result = stmt.executeQuery(sql);return result;在上面的代碼中,并沒(méi)有關(guān)閉ResultSet的代碼,直接返回ResultSet對(duì)象,我們還需要對(duì)ResultSet對(duì)象進(jìn)行一些處理,因此在這里不進(jìn)行關(guān)閉操作,該方法只是簡(jiǎn)單的進(jìn)行查詢。編寫(xiě)執(zhí)行SQL的方法,代碼清單:codebooksrcorgcrazyitbookjd
52、bcJDBCExecutor.java/執(zhí)行單句INSERT、UPDATE 或 DELETE 語(yǔ)句, 如果執(zhí)行INSERT時(shí), 返回主鍵public int executeUpdate(String sql) int result = -1;/執(zhí)行SQL語(yǔ)句stmt.executeUpdate(sql);/獲得主鍵ResultSet rs = stmt.getGeneratedKeys();while(rs.next() result = rs.getInt(1);/返回最后一個(gè)主鍵rs.close();return result;在以上代碼中,將會(huì)返回執(zhí)行該句SQL所產(chǎn)生的主鍵。到這里,我們
53、的JDBCExecutor類已經(jīng)編寫(xiě)完了。9.4.4創(chuàng)建數(shù)據(jù)轉(zhuǎn)換工具類在9.4.3中,JDBCExecutor中提供了一個(gè)executeQuery方法,該方法返回ResultSet對(duì)象,當(dāng)時(shí)我們并沒(méi)有關(guān)閉ResultSet,這是由于我們需要對(duì)該結(jié)果集進(jìn)行一些封裝。在本小節(jié)中將建立一個(gè)工具類,進(jìn)該結(jié)果集進(jìn)行封裝,并返回對(duì)應(yīng)的集合。在9.4.1中,我們?cè)O(shè)計(jì)了各個(gè)表所對(duì)應(yīng)的類,那么在封裝的過(guò)程中,將結(jié)果集(ResultSet)中的某個(gè)值作為這些類(表對(duì)象)的屬性,并負(fù)責(zé)創(chuàng)建這些對(duì)象,放到集合中去。新建DataUtil類,具體的代碼如下。代碼清單:codebooksrcorgcrazyitbookco
54、mmonsDataUtil.java/將rs中的值封裝成一個(gè)集合public static Collection getDatas(Collection result, ResultSet rs, Class clazz) while (rs.next() /創(chuàng)建類的實(shí)例Object vo = clazz.newInstance();/獲取本對(duì)象的屬性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í)行一個(gè)方法, 從ResultSet中獲取一個(gè)字段的數(shù)據(jù), 調(diào)用vo的setter方法private static void invokeMethod(ResultSet rs, Field field, Object vo, Method setterMethod) /當(dāng)使用ResultSet獲取某個(gè)字段的時(shí)候, 如果沒(méi)有該字段, 會(huì)出現(xiàn)SQLException, 在這里忽略該異常String value = rs.getString(field.getName();/從ResultSet中獲取與該對(duì)象屬性名一致的字段, 并執(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;/相加兩個(gè)數(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)建類的實(shí)例,再獲得父類和本類的屬性,再通過(guò)setter方法將ResultSet中對(duì)應(yīng)的值設(shè)置到對(duì)象中。我們?cè)?.4.1中,約定了各個(gè)類的屬性命名都需要與數(shù)據(jù)庫(kù)中的表字段一致,在這里,我
59、們很容易就可以得到某個(gè)字段的setter方法,并可以根據(jù)類的屬性名稱得到ResultSet中對(duì)應(yīng)的字段值。在本例中,父類就是ValueObject,ValueObject中有一個(gè)ID屬性,就對(duì)應(yīng)了各個(gè)表中的ID字段。ValueObject下面的各個(gè)子類的class都可以作為getDatas的clazz參數(shù)傳入,從而創(chuàng)建傳入類的對(duì)象。簡(jiǎn)單的說(shuō),DataUtil就是根據(jù)ResultSet來(lái)創(chuàng)建ValueObject的集合,當(dāng)創(chuàng)建完后,就需要在這里關(guān)閉ResultSet對(duì)象。這也是為什么在JDBCExecutor不需要關(guān)閉ResultSet的原因。到這里,開(kāi)發(fā)的準(zhǔn)備工作已經(jīng)全部完成了,在本小節(jié)中,描
60、述了如何連接JDBC進(jìn)行數(shù)據(jù)庫(kù)連接,使用Java的反射進(jìn)行字段與類屬性的映射,這些都為我們后面的功能開(kāi)發(fā)打好了基礎(chǔ),在開(kāi)發(fā)的過(guò)程中,我們可以直接編寫(xiě)SQL,得到結(jié)果集,傳遞給DataUtil類,讓它轉(zhuǎn)換成集合,我們不再需要去處理ResultSet、Connection和Statement等對(duì)象。9.5 出版社管理功能從本小節(jié)開(kāi)始,我們開(kāi)始實(shí)現(xiàn)系統(tǒng)功能,從最簡(jiǎn)單的出版社管理功能開(kāi)始,由于出版社表中不涉及任何的外鍵,界面中只有一個(gè)簡(jiǎn)單的列表和表單,實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單。9.5.1 分層結(jié)構(gòu)我們可以將系統(tǒng)分為三層:表現(xiàn)層、業(yè)務(wù)層、數(shù)據(jù)訪問(wèn)層,這樣分層的好處在于,如果視圖層發(fā)生變化,例如不再使用swing
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 頂崗老師班會(huì)課件模板
- 金屬冶煉負(fù)責(zé)人安管人員培訓(xùn)
- 音樂(lè)課國(guó)防教育課件
- 水肌酸產(chǎn)品項(xiàng)目運(yùn)營(yíng)管理方案
- 電網(wǎng)側(cè)獨(dú)立儲(chǔ)能示范項(xiàng)目經(jīng)濟(jì)效益和社會(huì)效益分析報(bào)告
- 城鎮(zhèn)污水管網(wǎng)建設(shè)項(xiàng)目人力資源管理方案(模板范文)
- xx片區(qū)城鄉(xiāng)供水一體化項(xiàng)目建設(shè)管理方案
- 先進(jìn)金屬材料行動(dòng)計(jì)劃
- 無(wú)人駕駛配送車(chē)輛定位精度提升
- 2025年井下多功能測(cè)振儀項(xiàng)目建議書(shū)
- (高清版)DB11∕T 2429-2025 補(bǔ)充耕地質(zhì)量調(diào)查與評(píng)價(jià)技術(shù)規(guī)范
- 2025年貴州省6月28日納雍事業(yè)單位教師崗考試真題及答案
- 提高冠脈介入手術(shù)術(shù)前準(zhǔn)備的合格率護(hù)理品管圈QCC成果匯報(bào)課件(完整內(nèi)容可編輯修改)
- 機(jī)關(guān)檔案管理工作培訓(xùn)PPT課件
- 油輪、化學(xué)品船的基本知識(shí)
- 25T汽車(chē)吊檢驗(yàn)報(bào)告
- 變頻空調(diào)中的永磁電機(jī)電感分析
- 高考??颊Z(yǔ)法填空詞性轉(zhuǎn)換匯總
- AOI自動(dòng)光學(xué)檢測(cè)設(shè)備程序編寫(xiě)
- 廈門(mén)護(hù)士延續(xù)注冊(cè)體檢表
- GB∕T 386-2021 柴油十六烷值測(cè)定法
評(píng)論
0/150
提交評(píng)論