第18章 運用Struts+Hibernate開發物資管理系統
Hibernate作為一個成熟且功能強大的持久層框架,它對JDBC進行了輕量級的對象封裝,使程序員可能隨心所欲地使用面向對象編程思想來操縱數據庫。Struts作為一款優秀的基于MVC的Java Web框架,已經得到了廣大企業和Java Web程序員的認可。Struts+Hibernate可謂開發Web程序的黃金組合。
本章將介紹運用Struts+Hibernate開發物資管理系統的全過程。本系統具有以下亮點。
● 通過Struts框架實現MVC模式,不但可以提高網站的開發速度,而且可以增強程序的可讀性和易維護性。
● 系統中采用了Struts的RequestProcessor類解決中文亂碼問題,使原本繁瑣的工作變得非常簡單。
● 通過Hibernate的HQL查詢及關聯操作使數據檢索操作變得簡單易行。
服務器端:
● 操作系統:Windows 2000 Server
● Web服務器:Tomcat 5.5
● 開發工具包:JDK Version 1.5以上
● 數據庫:SQL Server 2000
● 瀏覽器:IE 6.0
● 分辨率:最佳效果1024×768像素
客戶端:
● 瀏覽器:IE 6.0及以上版本,推薦使用IE 6.0
● 分辨率:最佳效果1024×768像素
18.1 需 求 分 析
物資管理是企業管理非常重要的一環,它對企業的發展起著非常舉足輕重的作用。由于物資的種類繁多,在各部門進出頻繁,使得物資管理變得十分復雜。開發一套完善的物資管理系統不但可以使物資的管理者能夠對物資的整個流程狀態、庫存狀況了如指掌,并為決策管理提供科學依據,從而提高了管理水平和工作效率,而且可以使工作人員甩掉手工記賬方式,從而最大限度地減少了手工操作帶來的失誤,達到事半功倍的效果。物資管理系統作為企業管理自動化、規范化的一部分,對提高企業管理效率、提高企業經濟效益發揮不可替代的作用。
18.2 系 統 設 計
18.2.1 項目規劃
物資管理系統是一個典型的數據庫應用程序,由物資入庫、物資出庫、物資處理、查詢統計、基礎信息、系統管理、修改密碼等模塊組成,其各功能模塊如下。
● 物資入庫
物資入庫主要實現創建采購單、審核入庫、借出歸還等功能。
● 物資出庫
物資出庫主要實現部門領用、物資借出、借出審核等功能。
● 物資處理
物資處理主要實現庫存盤點、部門報損等功能。
● 查詢統計
查詢統計主要實現采購單查詢、入庫查詢、部門領用查詢、部門領用匯總、部門報損查詢、部門報損匯總、借出查詢、部門匯總等功能。
● 基礎信息
基礎信息主要實現供應商信息管理、物資信息管理、部門信息管理等功能。
● 系統管理
系統管理主要實現用戶管理、系統初使化等功能。
● 修改密碼
修改密碼主要用于修改登錄用戶的密碼。
18.2.2 系統功能結構
物資管理系統功能結構如圖18.1所示。
18.2.3 業務流程
物資管理系統的業務流程如圖18.2所示。

圖18.1 系統功能結構圖

圖18.2 業務流程圖
18.3 數據庫設計
本系統采用的SQL Server 2000數據庫,數據庫名為db_Material,共包含12張數據表和一張視圖。下面分別給出各數據表、視圖的簡要說明,數據表之間的關系及主要數據表的結構。
18.3.1 數據表、視圖的簡要說明
數據表、視圖樹型結構如圖18.3所示,該數據表樹型結構圖包含本系統中使用的所有用戶數據表。

圖18.3 數據表及視圖樹型結構圖
18.3.2 數據表關系概要說明
物資管理系統的數據表關系如圖18.4所示。

圖18.4 數據表關系圖
18.3.3 主要數據表的結構
● tb_goods(物資信息表)
物資信息表主要用于保存物資基本信息。表tb_goods的結構如表18.1所示。
表18.1 tb_goods表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
是
|
Hibernate自動編號
|
name
|
varchar
|
50
|
否
|
物資名稱
|
spec
|
varchar
|
50
|
否
|
規格
|
unit
|
varchar
|
6
|
否
|
單位
|
price
|
float
|
8
|
否
|
單價
|
producer
|
varchar
|
50
|
否
|
生產廠家
|
ifdel
|
bit
|
1
|
否
|
是否刪除
|
● tb_branch(部門信息表)
部門信息表主要用于保存部門信息。表tb_branch的結構如表18.2所示。
表18.2 tb_branch表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
Id
|
int
|
4
|
是
|
Hibernate自動編號
|
Name
|
varchar
|
30
|
否
|
部門名稱
|
Tel
|
varchar
|
20
|
否
|
部門電話
|
Memo
|
varchar
|
100
|
否
|
備注
|
● tb_stock_main(采購單主表)
采購單主表主要用于保存采購單概要信息。表tb_stock_main的結構如表18.3所示。
表18.3 tb_stock_main表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
sno
|
varchar
|
17
|
否
|
采購單號
|
principal
|
varchar
|
30
|
否
|
負責人
|
providerid
|
int
|
4
|
否
|
供應商ID
|
username
|
varchar
|
30
|
否
|
操作員
|
createTime
|
smalldatetime
|
4
|
否
|
開單日期
|
state
|
int
|
4
|
否
|
狀態(0表示未審核;1表示審核合格;2表示審核不合格)
|
● tb_stock_detail(采購單明細表)
采購單明細表主要用于保存采購單的明細信息。表tb_stock_detail的結構如表18.4所示。
表18.4 tb_stock_detail表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
stockid
|
int
|
4
|
否
|
采購單號
|
goodsid
|
int
|
4
|
否
|
物資ID
|
price
|
money
|
8
|
否
|
單價
|
number
|
int
|
4
|
否
|
數量
|
● tb_storage(庫存表)
庫存表主要用于保存物資的庫存信息。表tb_storage的結構如表18.5所示。
表18.5 tb_storage表
字 段 名 稱
|
數 據 類 型
|
字段大小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
goodsid
|
int
|
4
|
否
|
物資ID
|
number
|
bigint
|
8
|
否
|
庫存數量
|
● tb_instorage(入庫表)
入庫表主要用于保存物資的入庫信息。表tb_instorage的結構如表18.6所示。
表18.6 tb_instorage表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
ino
|
varchar
|
17
|
否
|
入庫單號
|
stockid
|
int
|
4
|
否
|
采購單號
|
createtime
|
smalldatetime
|
4
|
否
|
入庫日期
|
username
|
varchar
|
30
|
否
|
操作員
|
● tb_getUse(部門領用信息表)
部門領用信息表主要用于保存部門領用信息。表tb_getUse的結構如表18.7所示。
表18.7 tb_getUse表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
gno
|
varchar
|
17
|
否
|
領用ID
|
goodsid
|
int
|
4
|
否
|
物資ID
|
number
|
int
|
4
|
否
|
領用數量
|
principal
|
varchar
|
20
|
否
|
負責人
|
username
|
varchar
|
30
|
否
|
操作員
|
branchid
|
int
|
4
|
否
|
部門ID
|
createtime
|
smalldatetime
|
4
|
否
|
領用時間
|
● tb_loan(物資借出信息表)
物資借出信息表主要用于保存物資借出信息。表tb_loan的結構如表18.8所示。
表18.8 tb_loan表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
lno
|
varchar
|
17
|
否
|
借出編號
|
goodsid
|
int
|
4
|
否
|
物資ID
|
number
|
int
|
4
|
否
|
借出數量
|
username
|
varchar
|
30
|
否
|
操作員
|
principal
|
varchar
|
30
|
否
|
負責人
|
borrowperson
|
varchar
|
20
|
否
|
借用人
|
btel
|
varchar
|
20
|
否
|
借用人電話
|
bunit
|
varchar
|
30
|
否
|
借用人單位
|
createtime
|
smalldatetime
|
4
|
否
|
借出時間
|
state
|
smallint
|
2
|
否
|
狀態
|
taster
|
varchar
|
20
|
否
|
審核人
|
approvetime
|
smalldatetime
|
4
|
否
|
審核時間
|
backperson
|
varchar
|
20
|
否
|
歸還人
|
backtime
|
smalldatetime
|
4
|
否
|
歸還時間
|
● tb_damage(部門報損信息表)
部門報損信息表主要用于保存部門報損信息。表tb_loan的結構如表18.9所示。
表18.9 tb_loan表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
是
|
Hibernate自動編號
|
branchid
|
int
|
4
|
否
|
部門ID
|
goodsid
|
int
|
4
|
否
|
物資ID
|
續表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
damagenum
|
Int
|
4
|
否
|
報損數量
|
createtime
|
smalldatetime
|
4
|
否
|
報損時間
|
principal
|
varchar
|
20
|
否
|
負責人
|
username
|
varchar
|
30
|
否
|
操作員
|
cause
|
varchar
|
100
|
否
|
報損原因
|
● tb_user(用戶信息表)
用戶信息表主要用于保存用戶及其權限信息。表tb_user的結構如表18.10所示。
表18.10 tb_user表
字 段 名 稱
|
數 據 類 型
|
字 段 大 小
|
是 否 主 鍵
|
說 明
|
id
|
int
|
4
|
否
|
Hibernate自動編號
|
name
|
varchar
|
30
|
否
|
用戶名
|
pwd
|
varchar
|
30
|
否
|
密碼
|
setInstorage
|
bit
|
1
|
否
|
物資入庫
|
setOutstorage
|
bit
|
1
|
否
|
物資出庫
|
setDeal
|
bit
|
1
|
否
|
物資處理
|
setQuery
|
bit
|
1
|
否
|
查詢統計
|
setBasic
|
bit
|
1
|
否
|
基礎信息
|
setSys
|
Bit
|
1
|
否
|
系統管理
|
18.4 網站總體設計
18.4.1 文件夾架構設計
在編寫代碼之前,可以把系統中可能用到的文件夾先創建出來(例如:創建一個名為image的文件夾,用于保存網站中所使用的圖片),這樣不但可以方便以后的開發工作,也可以規范網站的整體架構。筆者在開發物資管理系統時,設計了如圖18.5所示的文件夾架構圖。在開發時,只需要將所創建的文件保存在相應的文件夾中就可以了。

圖18.5 文件夾架構圖
18.4.2 類的分布架構設計
為了方便讀者閱讀和有效利用本書附贈光盤中的實例,下面給出系統中使用的類和.xml文件的描述信息,如圖18.6所示。

圖18.6 類的分布架構圖
18.4.3 文件架構
物資管理系統的文件架構如圖18.7所示。

圖18.7 物資管理系統文件架構
18.4.4 網站首頁架構
用戶通過“用戶登錄”模塊即可登錄到物資管理系統的主界面。系統主界面主要用于根據登錄用戶的權限,顯示該用戶可操作的功能菜單。系統主界面的運行結果如圖18.8所示。

圖18.8 系統主界面的運行結果
為了方便讀者閱讀和有效利用本書附贈光盤中的實例,筆者將系統主界面的各部分說明以列表形式給出,如表18.11所示。
表18.11 系統主界面說明
區 域
|
名 稱
|
說 明
|
對 應 文 件
|
1
|
系統導航
|
主要展示系統菜單、當前系統日期及當前登錄用戶,同時該頁面還具有防止非法用戶登錄系統的功能
|
top.jsp
|
2
|
業務操作區
|
為業務操作提供顯示平臺
|
main.jsp
|
3
|
版權信息
|
顯示系統的版權信息
|
copyright.jsp
|
18.5 配置Struts
Struts框架需要通過一個專門的配置文件來控制,它就是struts-config.xml,當然也可以取其他名字。網站在“WEB-INF\web.xml”文件中配置一下就可以找到這個Struts配置文件,具體代碼如下。
例程18-1:光盤\mr\18\MaterialManage\defaultroot\WEB-INF\web.xml
<display-name>defaultroot</display-name>
<jsp-config>
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<!—此處省略了配置HTML標簽路徑的代碼-->
</jsp-config>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>debugjsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
</web-app>
在web.xml中配置Struts的配置文件,實際就是一個Servlet的配置過程,在配置Servlet的config參數中定義Struts的配置文件(包括相對路徑),及在Servlet的URL訪問里使用的后綴名,本實例中使用“.do”作為后綴名。
接下來的工作就是配置struts-config.xml文件。本實例中的struts-config.xml文件的關鍵代碼如下。
例程18-2:光盤\mr\18\MaterialManage\defaultroot\WEB-INF\struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean name="goodsForm" type="com.actionForm.GoodsForm" />
…… //此處省略了其他<form-bean>代碼
</form-beans>
<action-mappings>
<action name="goodsForm" path="/goods" scope="request" type="com.action.Goods" validate="true">
<forward name="error" path="/error.jsp" />
<forward name="goodsQuery" path="/goodsList.jsp" />
<forward name="goodsaddok" path="/goods_ok.jsp?para=1" />
<forward name="goodsModiQuery" path="/goodsModify.jsp" />
<forward name="goodsmodifyok" path="/goods_ok.jsp?para=2" />
<forward name="goodsdelok" path="/goods_ok.jsp?para=3" />
</action>
…… //此處省略了其他<action></action>代碼
</action-mappings>
<controller processorClass="com.action.SelfRequestProcessor" />
<message-resources parameter="ApplicationResources" />
</struts-config>
注意:在使用JBuilder開發應用Struts框架的程序時,web.xml和struts-config.xml文件的配置都將由JBuilder完成。
18.6 配置Hibernate配置文件
創建物資管理系統的Hibernate配置文件hibernate.cfg.xml,該文件中存放著數據庫連接驅動程序類、登錄數據庫的用戶名/密碼、映射持久化類配置文件的位置等,Hibernate初始化時會自動在classes路徑中尋找這個文件,并讀取其中的配置信息,為后期數據庫操作做準備,其完整代碼如下。
例程18-3:光盤\mr\18\MaterialManage\defaultroot\WEB-INF\classes\hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class"><!--指定連接數據庫用的驅動-->
com.microsoft.jdbc.sqlserver.SQLServerDriver
</property>
<property name="connection.url"><!--指定連接數據庫的路徑-->
jdbc:microsoft:sqlserver://127.0.0.1:1433;databaseName=db_Material
</property>
<property name="connection.username">sa</property><!--指定連接數據庫的用戶名-->
<property name="connection.password"></property><!--指定連接數據庫的密碼-->
<property name="show_sql">true</property><!--當show_sql屬性為true時表示在程序運行時在控制臺輸出SQL語句,默認為false,建議在調試程序時設為true,發布程序之前再改為false,因為輸出SQL語句會影響程序的運行速度-->
<mapping resource="com/actionForm/GoodsForm.hbm.xml"/><!--指定持久化類映射文件-->
…… <!--此處省略了指定其他持久化類映射文件的代碼-->
</session-factory>
</hibernate-configuration>
注意:在運行光盤中提供的實例程序時,如果登錄用戶不是sa和空密碼,可以根據實際情況修改該文件。
18.7 公共類的編寫
在開發過程中,經常會用到一些公共類,如Session管理類及獲取日期和時間的類,因此在開發系統前首先應該編寫這些工具類。下面將具體介紹物資管理系統中所需要的公共類的編寫過程。
18.7.1 Session管理類的編寫
Session管理類主要包括獲得SessionFactory的代碼和打開Session、關閉Session的方法。下面將詳細介紹如何編寫物資管理系統的Session管理類MySession。
(1)定義MySession類,將其保存到com.core包中,并編寫獲得SessionFactory的代碼,同時導入所需的類包,代碼如下。
例程18-4:光盤\mr\18\MaterialManage\src\com\core\MySession.java
package com.core;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
public class MySession {
static SessionFactory sessionFactory;
static {
try {
Configuration config = new Configuration().configure();
sessionFactory = config.buildSessionFactory();
} catch (Exception e) {
System.out.println("創建SessionFactory時的錯誤信息:" + e.getMessage());
}
}
…… 此處省略的代碼將在步驟(2)-(3)中給出
}
(2)編寫打開Session的方法openSession,openSession方法的代碼如下。
例程18-5:光盤\mr\18\MaterialManage\src\com\core\MySession.java
public static Session openSession() {
Session session = sessionFactory.openSession();
return session;
}
(3)編寫關閉Session的方法getDateTime,getDateTime方法的代碼如下。
例程18-6:光盤\mr\18\MaterialManage\src\com\core\MySession.java
public static void closeSession(Session session) {
if (session != null) {
session.close();
}
}
18.7.2 獲取日期和時間類的編寫
獲取日期和時間的類主要包括獲取系統日期、獲取系統日期和時間、格式化日期時間的方法。下面將詳細介紹如何編寫獲取日期和時間的類GetTime。
(1)定義GetTime類,將其保存到com.core包中,并導入所需的類包,代碼如下。
例程18-7:光盤\mr\18\MaterialManage\src\com\core\GetTime.java
package com.core;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class GetTime {
…… 此處省略的代碼將在步驟(2)-(4)中給出
}
(2)編寫獲取系統日期的方法getDate,getDate方法的代碼如下。
例程18-8:光盤\mr\18\MaterialManage\src\com\core\GetTime.java
public Date getDate(){
Date dateU = new Date();
java.sql.Date date = new java.sql.Date(dateU.getTime());
System.out.println(date);
return date;
}
(3)編寫獲取系統日期和時間的方法getDateTime,getDateTime方法的代碼如下。
例程18-9:光盤\mr\18\MaterialManage\src\com\core\GetTime.java
public String getDateTime(){
SimpleDateFormat format;
Date date=null;
Calendar myDate=Calendar.getInstance();
myDate.setTime(new java.util.Date());
date=myDate.getTime();
format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String rtnStr=format.format(date);
return rtnStr;
}
(4)編寫格式化日期時間為“年-月-日 時:分:秒”格式的方法formatTime,formatTime方法的代碼如下。
例程18-10:光盤\mr\18\MaterialManage\src\com\core\GetTime.java
public String formatTime(Date date){
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str=format.format(date);
return str;
}