18.11 物资出库模块
18.11.1 物资出库模块总体架构
物资出库模块主要包括以下功能:
● 部门领用:用于对部门领用信息进行登记;
● 物资借出:用于对物资借出信息进行登记;
● 借出审核:用于对物资借出信息进行审核。
18.11.2 创建物资出库模块的持久化类及映射文件
1.创建持久化类和映射文件
物资出库模块涉及到的数据表的持久化类和映射文件如表18.18所示。持久化类及映射文件的具体实现方法请参见18.8.2节。
表18.18 物资出库模块涉及到的数据表的持久化类和映射文件
数据表名称 |
持久化类名称 |
映射文件名称 |
tb_getUse |
GetUseForm |
GetUseForm.hbm.xml |
tb_branch |
BranchForm |
BranchForm.hbm.xml |
tb_loan |
LoanForm |
LoanForm.hbm.xml |
tb_goods |
GoodsForm |
GoodsForm.hbm.xml |
tb_storage |
StorageForm |
StorageForm.hbm.xml |
2.映射关联关系
在物资出库模块中,涉及到3对关联关系,如表18.19所示。
表18.19 物资出库模块的表间关系
主 键 表 |
外 键 表 |
||
名 称 |
字 段 名 |
名 称 |
字 段 名 |
tb_goods |
id |
tb_getUse |
goodsid |
tb_branch |
id |
tb_getUse |
branchid |
tb_goods |
id |
tb_loan |
goodsid |
说明:在Hibernate中映射关联关系的具体方法请参见18.10.2节。
3.修改Hibernate配置文件
在创建持久化类、映射文件和关联关系后,还需要在Hibernate配置文件hibernate.cfg.xml中指定持久化类映射文件,关键代码如下:
<mapping resource="com/actionForm/GetUseForm.hbm.xml"/>
<mapping resource="com/actionForm/LoanForm.hbm.xml"/>
<mapping resource="com/actionForm/BranchForm.hbm.xml"/>
说明:由于物资信息持久化类及映射文件已经在18.9.2节介绍了,所以此时不需要再配置了。
18.11.3 创建物资出库的Action实现类
物资出库模块涉及到两个Action实现类,一个是用于部门领用操作的GetUse类,另一个是用于物资借出操作的Loan类,下面将分别介绍。
1.创建部门领用操作的Action实现类GetUse
在部门领用操作的Action实现类GetUse中首先需要在构造方法中实例化物资出库模块的OutStorageDAO类(该类用于实现业务逻辑操作),然后通过Action实现类的主要方法execute()执行相应的业务逻辑操作。Action实现类的execute()方法会被自动执行,这个方法本身没有具体的事务,它是根据HttpServletRequest的getParameter()方法获取的action参数值执行相应方法的。
实现部门领用操作的Action实现类的关键代码如下。
例程18-92:光盘\mr\18\MaterialManage\src\com\action\GetUse.java
public class GetUse extends Action {
private OutStorageDAO outStorageDAO = null;
public GetUse() {
outStorageDAO = new OutStorageDAO();
}
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
String action = request.getParameter("action");
if (action.equals("") || action == null) {
request.setAttribute("error", "您的操作有误!");
return mapping.findForward("error");
} else if (action.equals("getuseaddquery")) { //查询库存中的物资信息
return getuseadd_request(mapping, form, request, response);
} else if (action.equals("getuseadd")) { //部门领用
return getuseadd(mapping, form, request, response);
}
request.setAttribute("error", "您的操作有误!");
return mapping.findForward("error");
}
…… //此处省略了该类中其他方法,这些方法将在后面的具体过程中给出
}
2.创建用于物资借出操作的Action实现类Loan
在用于物资借出操作的Action实现类Loan中,首先需要在构造方法中实例化物资出库模块的OutStorageDAO类(该类用于实现业务逻辑操作),然后通过Action实现类的主要方法execute()执行相应的业务逻辑操作。Action实现类的execute()方法会被自动执行,这个方法本身没有具体的事务,它是根据通过HttpServletRequest的getParameter()方法获取的action参数值执行相应方法的。实现物资借出操作的Action实现类Loan的关键代码如下。
例程18-93:光盘\mr\18\MaterialManage\src\com\action\Loan .java
public class GetUse extends Action {
…… //此处省略了在构造方法中实例化OutStorageDAO类的方法
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
String action = request.getParameter("action");
if (action.equals("") || action == null) {
request.setAttribute("error", "您的操作有误!");
return mapping.findForward("error");
} else if (action.equals("loanaddquery")) { //查询库存中的物资信息
return loanadd_request(mapping, form, request, response);
} else if (action.equals("loanadd")) { //物资借出
return loanadd(mapping, form, request, response);
}else if(action.equals("approveloan")){ //借出审核
return approveloan(mapping, form, request, response);
}else if(action.equals("backloan")){ //借出归还
return backloan(mapping, form, request, response);
}else{
request.setAttribute("error", "您的操作有误!");
return mapping.findForward("error");
}
…… //此处省略了该类中其他方法,这些方法将在后面的具体过程中给出
}
18.11.4 部门领用设计
使用的数据表:tb_getuse、tb_branch、tb_goods、tb_storage
主要技术:通过Hibernate API操作数据库
用户登录后,选择“物资出库”→“部门领用”菜单项,进入到部门领用登记页面。在部门领用页面中,首先从“物资名称”下拉列表框中选择要领用的物资(系统将自动检索出该物资的生产厂家、单价、计量单位和库存数量等信息),然后在“领用数量”文本框中输入领用数量(系统会自动检验库存数量,如果库存数量不足,系统将给予提示),最后选择领用部门并输入负责人名称,单击【保存】按钮,保存部门领用信息,运行结果如图18.22所示。
图18.22 部门领用页面运行结果
1.设计部门领用页面
从系统主菜单中选择“物资出库”→“部门领用”菜单项或是在部门领用页面中改变“物资名称”下拉列表框的值时都会触发一个URL地址,这个URL地址是“getUse.do?action=getuseaddquery”,从这个URL地址中可以知道部门领用页面所涉及到的action的参数值为“getuseaddquery”,当action=getuseaddquery时,会调用查询库存中的物资信息的方法getuseadd_request(),具体代码如下。
例程18-94:光盘\mr\18\MaterialManage\src\com\action\GetUse.java
if (action.equals("getuseaddquery")) {
return getuseadd_request(mapping, form, request, response);
}
在查询库存物资信息的方法getuseadd_request()中,首先需要获取从页面中传递的参数id的值并保存到HttpServletRequest的对象id中,然后调用OutStorageDAO类中的storage_query()方法查询出库存中的物资信息,再将返回的查询结果保存到HttpServletRequest的对象GoodsStorage中。查询库存中物资信息的方法getuseadd_request()的具体代码如下。
例程18-95:光盘\mr\18\MaterialManage\src\com\action\GetUse.java
public ActionForward getuseadd_request(ActionMapping mapping,ActionForm form,
HttpServletRequest request,HttpServletResponse response) {
int goodsid = 0;
if (request.getParameter("id") != null) {
goodsid = Integer.parseInt(request.getParameter("id"));
}
request.setAttribute("id", goodsid);
request.setAttribute("GoodsStorage", outStorageDAO.storage_query()); //获取物资信息
return mapping.findForward("selStorageGoods");
}
从上面的代码中可以知道查询库存中物资信息使用的OutStorageDAO类的方法是storage_query(),在该方法中首先需要利用Hibernate的本地SQL查询从两个表中获取库存中物资的详细信息,然后将查询结果保存到List集合list中,并返回list。storage_query()方法的具体代码如下。
例程18-96:光盘\mr\18\MaterialManage\src\com\action\OutStorageDAO.java
public List storage_query() {
session = MySession.openSession(); //打开Session
String sql = "select {goods.*},{storage.*} from tb_goods goods inner join tb_storage storage on goods.id= storage.goodsid where storage.number>0"; //使用内连接查询库存信息
List list = null;
try {
SQLQuery query = session.createSQLQuery(sql);
query.addEntity("goods", GoodsForm.class); //将数据表与持久化类关联在一起
query.addEntity("storage", StorageForm.class);
list = query.list();
} catch (Exception e) {
System.out.println("查询时的错误信息:" + e.getMessage());
}
return list;
}
在struts-config.xml文件中配置查询库存中物资信息所涉及的<forward>元素,代码如下:
<forward name="selStorageGoods" path="/getUseAdd.jsp" />
接下来的工作是将Action实现类中的storage_query()方法返回的查询结果显示在部门领用页面getUseAdd.jsp中。在getUseAdd.jsp中通过request.getAttribute()方法获取查询结果并将其显示在相应的位置或表单元素中。
2.保存部门领用信息
在部门领用页面中录入部门领用信息后,单击【保存】按钮,系统会访问一个URL,这个URL是“getUse.do?action=getuseadd”。从该URL地址中可以知道保存部门领用信息涉及到的action的参数值为“getuseadd”,也就是当action=getuseadd时,会调用保存部门领用信息的方法getuseadd(),具体代码如下。
例程18-97:光盘\mr\18\MaterialManage\src\com\action\GetUse.java
if (action.equals("getuseadd")) {
return getuseadd(mapping, form, request, response);
}
在保存部门领用信息的方法getuseadd()中,首先需要将接收到的表单信息强制转换成ActionForm类型,然后调用OutStorageDAO类中的getuseAdd()方法保存部门领用信息到相应的数据表中,并将返回值保存到变量rtn中。如果返回值为1,表示信息修改成功,将页面重定向到部门领用页面,否则将错误提示信息“部门领用信息添加失败!”保存到HttpServletRequest的对象error中,然后将页面重定向到错误提示信息页面。保存部门领用信息的方法getuseadd()的关键代码如下。
例程18-98:光盘\mr\18\MaterialManage\src\com\action\GetUse.java
public ActionForward getuseadd(ActionMapping mapping, ActionForm form,
HttpServletRequest request,HttpServletResponse response) {
GetUseForm getUseForm = (GetUseForm) form;
int rtn = outStorageDAO.getuseAdd(getUseForm);
…… //此处省略了根据返回值重定向页面的代码
}
3.编写保存部门领用信息的OutStorageDAO类的方法
从上面的代码中可以知道保存部门领用信息时使用的OutStorageDAO类的方法是getuseAdd()。实现getuseAdd()方法主要分为以下4个步骤。
(1)将部门领用信息保存到部门领用信息表中,由于映射了关联关系,所以需要建立“GoodsForm和GetUseForm的关联关系”以及“BranchForm和GetUseForm的关联关系”。
(2)获取部门领用信息表中最大的自动编号,与字符“LY”和系统日期组合成“LYYYYY-MM-DDnnnnn”格式的领用单号,并插入到部门领用信息表中。
(3)修改库存信息表。
(4)如果在执行过程中不抛出异常,则将标志变量赋值为1,否则将标志变量赋值为0,最后返回该标志变量。
getuseAdd()方法的具体代码如下。
例程18-99:光盘\mr\18\MaterialManage\src\com\dao\OutStorageDAO.java
public int getuseAdd(GetUseForm getUseForm) {
session = MySession.openSession(); //打开Session
Transaction tx = null;
int rtn = 1;
try {
//保存部门领用信息
tx = session.beginTransaction();
int goodsid = getUseForm.getGoodsid();
GoodsForm goodsForm = (GoodsForm) session.get(GoodsForm.class,goodsid);
getUseForm.setGoods(goodsForm);
int branchid = getUseForm.getBranchid();
BranchForm branchForm = (BranchForm) session.get(BranchForm.class,branchid);
getUseForm.setBranch(branchForm);
getUseForm.setCreatetime(new Date());
session.save(getUseForm);
NumberFormat formater = NumberFormat.getNumberInstance();
int id = getUseForm.getId();
formater.setMinimumIntegerDigits(5);
java.util.Date createTime = getUseForm.getCreatetime();
java.sql.Date date = new java.sql.Date(createTime.getTime());
String gNo = "LY" + date +formater.format(id).toString().replace(",", ""); //组合领用单号
GetUseForm getUseF = (GetUseForm) session.get(
GetUseForm.class, id);
getUseF.setGno(gNo);
session.update(getUseF);
//修改库存信息
List list = session.createQuery("FROM StorageForm WHERE goodsid=" +
getUseForm.getGoodsid() + "").list();
StorageForm storageF = (StorageForm) list.get(0);
int storageNum = storageF.getNumber() - getUseForm.getNumber();
if (storageNum >= 0) {
storageF.setNumber(storageNum);
session.update(storageF);
} else { //库存数量不足
rtn = 0;
}
if (rtn == 1) {
tx.commit();
} else {
if (tx != null) {
tx.rollback();
}
}
} catch (Exception e) {
…… //此处省略了事务回滚和输出错误信息的代码
rtn = 0;
} finally {
MySession.closeSession(session); //关闭Session
}
return rtn;
}
4.struts-config.xml文件配置
在struts-config.xml文件中配置保存部门领用信息所涉及的<forward>元素,代码如下:
<forward name="getUseAddok" path="/getUseAdd_ok.jsp?para=1" />
18.11.5 物资借出设计
使用的数据表:tb_loan、tb_goods、tb_storage 主要技术:通过Hibernate API操作数据库
用户登录后,选择“物资出库”→“物资借出”菜单项,进入到 物资借出登记页面。在物资借出页面中。首先从“物资名称”下拉列表框中选择要借出的物资(系统将自动检索出该物资的生产厂家、单价、计量单位和库存数量等信息),然后在“借出数量”文本框中输入借出数量(系统会自动检验库存数量,如果库存数量不足,系统将给予提示),最后输入借用人基本信息及负责人名称,单击【保存】按钮,保存物资借出信息,运行结果如图18.23所示。
图18.23 物资借出页面运行结果
1.设计物资借出页面
从系统主菜单中选择“物资出库”→“物资借出”菜单项或是在物资借出页面中改变“物资名称”下拉列表框的值时都会触发一个URL地址,这个URL地址是“loan.do?action=loanaddquery”,从这个URL地址中可以知道物资借出页面所涉及到的action参数值为“loanaddquery”,当action=loanaddquery时,会调用查询库存中的物资信息的方法loanadd_request(),具体代码如下。
例程18-100:光盘\mr\18\MaterialManage\src\com\action\GetUse.java
if (action.equals("loanaddquery")) {
return loanadd_request(mapping, form, request, response);
}
在查询库存中物资信息的方法loanadd_request()中,首先需要获取从页面中传递的参数id的值并保存到HttpServletRequest的对象id中,然后调用OutStorageDAO类中的storage_query()方法查询出库存中的物资信息,再将返回的查询结果保存到HttpServletRequest的对象GoodsStorage中。查询库存中物资信息的方法getuseadd_request()的具体代码同例程18-98类似,这里就不再赘述。
查询库存中物资信息使用的OutStorageDAO类的方法是storage_query(),在该方法中首先需要利用Hibernate的本地SQL查询从两个表中获取库存中物资的详细信息,然后将查询结果保存到List集合list中,并返回list。storage_query()方法的具体代码请参见例程18-99。
在struts-config.xml文件中配置查询库存中物资信息所涉及的<forward>元素,代码如下:
<forward name="selStorageGoods" path="/getUseAdd.jsp" />
接下来的工作是将Action实现类中storage_query()方法返回的查询结果显示在物资借出页面loanAdd.jsp中。在loanAdd.jsp中通过request.getAttribute()方法获取查询结果并将其显示在相应的位置或表单元素中。
2.保存物资借出信息
在物资借出页面中录入物资借出信息后,单击【保存】按钮,系统会访问一个URL,这个URL是“loan.do?action=loanadd”。从该URL地址中可以知道保存物资借出信息涉及到的action的参数值为“loanadd”,也就是当action=loanadd时,会调用保存物资借出信息的方法loanadd(),具体代码如下。
例程18-101:光盘\mr\18\MaterialManage\src\com\action\Loan.java
if (action.equals("loanadd")) {
return loanadd(mapping, form, request, response);
}
在保存物资借出信息的方法loanadd()中,首先需要将接收到的表单信息强制转换成ActionForm类型,然后调用OutStorageDAO类中的getuseAdd()方法保存物资借出信息到相应的数据表中,并将返回值保存到变量rtn中,如果返回值为1,表示信息保存成功,将页面重定向到物资借出页面,否则将错误提示信息“物资借出信息添加失败!”保存到HttpServletRequest的对象error中,然后将页面重定向到错误提示信息页面。保存物资借出信息的方法loanadd()的关键代码如下。
例程18-102:光盘\mr\18\MaterialManage\src\com\action\Loan.java
public ActionForward loanadd(ActionMapping mapping, ActionForm form,
HttpServletRequest request,HttpServletResponse response) {
LoanForm loanForm = (LoanForm) form;
int rtn = outStorageDAO.loanAdd(loanForm);
…… //此处省略了根据返回值重定向页面的代码
}
3.编写保存物资借出信息的OutStorageDAO类的方法
从上面的代码中可以知道保存物资借出信息时使用的OutStorageDAO类的方法是loanAdd()。实现loanAdd()方法主要分为以下3个步骤。
(1)将物资借出信息保存到物资借出信息表tb_loan中。
(2)获取物资借出信息表中最大的自动编号,与字符“LY”和系统日期组合成“JCYYYY-MM-DDnnnnn”格式的借出单号,并插入到物资借出信息表中。
(3)如果在执行过程中不抛出异常,则将标志变量赋值为1,否则将标志变量赋值为0,最后返回该标志变量。
loanAdd()方法的具体代码如下。
例程18-103:光盘\mr\18\MaterialManage\src\com\dao\OutStorageDAO.java
public int loanAdd(LoanForm loanForm) {
session = MySession.openSession(); //打开Session
Transaction tx = null;
int rtn = 0;
try {
//保存物资借出信息
tx = session.beginTransaction();
int goodsid = loanForm.getGoodsid();
GoodsForm goodsForm = (GoodsForm) session.get(GoodsForm.class,goodsid);
loanForm.setGoods(goodsForm);
loanForm.setCreatetime(new Date());
session.save(loanForm);
NumberFormat formater = NumberFormat.getNumberInstance();
int id = loanForm.getId();
formater.setMinimumIntegerDigits(5);
java.util.Date createTime = loanForm.getCreatetime();
java.sql.Date date = new java.sql.Date(createTime.getTime());
String lNo = "JC" + date +formater.format(id).toString().replace(",", ""); //组合借出单号
LoanForm loanF = (LoanForm) session.get(
LoanForm.class, id);
loanF.setLno(lNo);
session.update(loanF);
tx.commit();
rtn = 1;
} catch (Exception e) {
…… //此处省略了事务回滚和输出错误信息的代码
rtn = 0;
} finally {
MySession.closeSession(session); //关闭Session
}
return rtn;
}
4.struts-config.xml文件配置
在struts-config.xml文件中配置保存物资借出信息所涉及的<forward>元素,代码如下:
<forward name="loanAddok" path="/loanAddok_ok.jsp?para=1" />
18.11.6 借出审核设计
使用的数据表:tb_loan、tb_goods、tb_storage 主要技术:通过Hibernate API操作数据库
用户登录后,选择“物资出库”→“借出审核”命令,进入到借出审核页面,在该页面中将显示全部未审核的借出单列表,单击审核图标,即可完成借出审核操作。借出审核页面的运行结果如图18.24所示。
图18.24 借出审核页面运行结果
在“借出审核”页面中可以找到审核图标的超级链接代码,如下所示:
例程18-104:光盘\mr\18\MaterialManage\defaultroot\loanApproveQuery.jsp
<a href="loan.do?action=approveloan&id=<%=id%>">
<img src="images/enforce.gif" width="16" height="16" border="0"></a>
从上面的URL地址中可以知道实现借出审核操作所涉及到的action的参数值为“approveloan”,当action=approveloan时,会调用实现借出审核操作的方法approveloan(),具体代码如下。
例程18-105:光盘\mr\18\MaterialManage\src\com\action\Loan.java
if(action.equals("approveloan")){
return approveloan(mapping, form, request, response);
}
在实现借出审核操作的方法approveloan()中,首先需要判断用户是否登录,如果没登录则跳转到登录页面强制其登录,这样可以提高系统的安全性,然后获取从页面中传递的参数id,并将id的值赋给int型变量id,赋值后将该变量作为OutStorageDAO类中approveloanAdd()方法的参数,最后调用approveloanAdd()方法实现借出审核操作,并根据执行结果转到相应的页面。approveloan()方法的具体代码如下。
例程18-106:光盘\mr\18\MaterialManage\src\com\action\Instorage.java
public ActionForward approveloan(ActionMapping mapping,ActionForm form,
HttpServletRequest request,HttpServletResponse response){
HttpSession httpsession = request.getSession();
…… //此处省略了判断用户是否登录的代码
int id=Integer.valueOf(request.getParameter("id"));
int rtn=outStorageDAO.approveloanAdd(id,request);
if(rtn==1){
return mapping.findForward("loanApproveAddok");
}else if(rtn==2){
request.setAttribute("error","库存数量不足,不能完成借出审核!");
return mapping.findForward("error");
}else{
request.setAttribute("error","借出审核操作失败!");
return mapping.findForward("error");
}
}
从上面代码中可以知道实现借出审核操作使用的OutStorageDAO类的方法是approveloanAdd()。在approveloanAdd()方法中首先将借出审核信息保存到物资借出信息表tb_loan中,然后修改相应物资的库存数量,当库存数量不足时,不能完成借出审核操作。approveloanAdd()方法的具体代码如下。
例程18-107:光盘\mr\18\MaterialManage\src\com\dao\OutStorageDAO.java
public int approveloanAdd(int id, HttpServletRequest request) {
int rtn = 1;
session = MySession.openSession(); //打开session
Transaction tx = null;
try {
tx = session.beginTransaction();
LoanForm loanForm = (LoanForm) session.get(LoanForm.class, id);
loanForm.setApprovetime(new Date());
HttpSession httpsession = request.getSession();
loanForm.setTaster((String) httpsession.getAttribute("username"));//设置审核员
loanForm.setState(new Short("1")); //修改借出单状态为已审核
session.update(loanForm); //保存借出审核信息
GoodsForm goodsF = loanForm.getGoods();
int goodsid = goodsF.getId();
int goodsnumber = loanForm.getNumber();
String hql_goods = "FROM StorageForm WHERE goodsid=" + goodsid + "";
List list_goods = session.createQuery(hql_goods).list();
if (list_goods.size() > 0) {
StorageForm storageF = (StorageForm) list_goods.get(0);
if (storageF.getNumber() - goodsnumber >= 0) {
String hql_up = "UPDATE StorageForm set number=number-" +
goodsnumber + " WHERE goodsid=" + goodsid +"";
session.createQuery(hql_up).executeUpdate();
} else {
rtn = 2; //库存不足
}
} else {
rtn = 0;
}
if (rtn == 1) {
tx.commit();
} else {
if (tx != null) {
tx.rollback();
}
}
} catch (Exception e) {
…… //此处省略了事务回滚和输出错误信息的代码
rtn = 0;
} finally {
MySession.closeSession(session); //关闭Session
}
return rtn;
}
在struts-config.xml文件中配置实现借出审核操作所涉及的<forward>元素,代码如下:
<forward name="loanApproveAddok" path="/loanAddok_ok.jsp?para=2" />