18.14  系统初始化模块
用户登录后,选择“系统管理”→“系统初使化”菜单项,进入到系统初使化,在该页面中将显示提示信息,单击【进行系统初使化】按钮,将进行系统初使化操作。系统初始化页面运行结果如图18.31所示。

图18.31  系统初始化页面运行结果
18.14.1  创建系统初始化模块的业务逻辑类
创建系统初始化模块的业务逻辑类SysDAO,将其保存在com.dao包中,该类主要用于清空系统中的除用户信息表以外的所有数据表和删除用户信息表中除超级用户mr以外的全部用户。值得注意的是:在删除存在关联关系的数据表时,需要先删除子表信息,再删除主表信息,否则将发生错误。
系统初始化模块的业务逻辑类SysDAO的关键代码如下。
例程18-136:光盘\mr\18\MaterialManage\src\com\action\SysDAO .java
public class SysDAO {
    public SysDAO(){
    }
    private Session session = null;
    public int sysinitialize(){
        session = MySession.openSession(); //打开Session
        Transaction tx = null;
        int rtn = 0;
        try {
            tx=session.beginTransaction();
            //删除用户信息
            session.createQuery("DELETE UserForm where name<>'mr'").executeUpdate(); 
            session.createQuery("DELETE GetUseForm").executeUpdate();   //清空部门领用信息表
            session.createQuery("DELETE DamageForm").executeUpdate();   //清空部门报损信息表
            session.createQuery("DELETE CheckForm").executeUpdate();      //清空审核信息表
            session.createQuery("DELETE InStorageForm").executeUpdate();     //清空入库信息表
            session.createQuery("DELETE StockDetailForm").executeUpdate();    //清空采购明细表
            session.createQuery("DELETE StockMainForm").executeUpdate();      //清空采购主表
            session.createQuery("DELETE ProviderForm").executeUpdate();    //清空供应商信息表
            session.createQuery("DELETE LoanForm").executeUpdate();     //清空物资借出信息表
            session.createQuery("DELETE StorageForm").executeUpdate();           //清空库存信息表
            session.createQuery("DELETE BranchForm").executeUpdate();           //清空部门信息表
            session.createQuery("DELETE GoodsForm").executeUpdate();           //清空商品信息表
            rtn=1;
            tx.commit();
        }catch(Exception e){
            if(tx!=null){
                tx.rollback();
            }
            e.printStackTrace();
            System.out.println("系统初使化时的错误信息:"+e.getMessage());
            rtn=0;
        } finally {
            MySession.closeSession(session);
        }
        return rtn;
    }
}
18.14.2  系统初始化页面设计
系统初使化模块共包括两个JSP页面,一个是用于显示提示信息的initialize.jsp,另一个是用于执行系统初使化操作的处理页initialize_deal.jsp。由于initialize.jsp页面比较简单,此处不作介绍,下面介绍如何实现initialize_deal.jsp页。
在执行系统初使化操作的处理页initialize_deal.jsp中,首先使用<jsp:useBean>动作指令生成SysDAO类的一个实例对象sysDAO,然后通过该实例对象调用SysDAO类的sysinitialize()方法,最后根据返回结果显示相应的提示信息,具体代码如下。
例程18-137:光盘\mr\18\MaterialManage\defaultroot\initialize_deal.jsp
<%@ page contentType="text/html; charset=gb2312" language="java"%>
<jsp:useBean id="sysDAO" class="com.dao.SysDAO" scope="request"/>
<%
int rtn=sysDAO.sysinitialize();
if(rtn==0){
    out.println("<script>alert('系统初使化失败!');window.location.href='initialize.jsp';</script>");
}else{
    out.println("<script>alert('系统初使化成功!\\r当前系统中只有mr一个用户,请重新登录!');window. 
 location.href='index.jsp'</script>"); 
}
%>
18.15  疑难问题分析与解决
18.15.1  在Struts中解决中文乱码
通常情况下解决中文乱码采用的是编写一个将ISO-8859-1编码转换为gb2312编码的方法,然后在出现乱码的位置调用该方法即可达到解决中文乱码的目的,但是这样做很不方便。Struts提供了一个快速解决中文乱码的方法,那就是通过配置和扩展RequestProcessor类实现。下面将详细介绍在Struts中解决中文乱码的方法。
(1)创建SelfRequestProcessor.java类文件,该类继承了RequestProcessor类,并重写processPreprocess()方法,在该方法中设置Request对象的请求编码为gb2312编码,具体代码如下。
例程18-138:光盘\mr\18\MaterialManage\src\com\action\SelfRequestProcessor.java
package com.action;
import org.apache.struts.action.RequestProcessor;
import javax.servlet.http.*;
import java.io.*;
public class SelfRequestProcessor extends RequestProcessor  {
    public SelfRequestProcessor() {
    }
    protected boolean processPreprocess(HttpServletRequest request,HttpServletResponse response){
        try {
            request.setCharacterEncoding("gb2312");
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }
        return true;
    }
}
(2)在struts-config.xml文件中利用<controller>元素配置自定义控制器组件SelfRequest Processor,用于对请求的参数进行转码,具体代码如下:
<controller processorClass="com.action.SelfRequestProcessor" />
配置<controller>元素主要是为了能让Struts识别开发者自定义的控制器组件。
18.15.2  部门汇总模块SQL语句解析
在部门汇总模块中需要将部门领用信息和部门报损信息按部门进行汇总并统计各部门正在使用物资的数量和金额,这可以通过以下SQL语句实现:
select g.name,g.spec,g.unit,g.price,t.branchname,t.lyamount,t.bsamount,
(t.lyamount-t.bsamount) zyamount from tb_goods g inner join ( select goodsid,branchname,
sum(bsamount) bsamount,sum(lyamount) lyamount from(select getuse.goodsid,0 as bsamount,
sum(getuse.number) as lyamount,branch.name as branchname from tb_getuse getuse inner join
 tb_branch branch on getuse.branchid=branch.id group by branch.name,getuse.goodsid
union select damage.goodsid,sum(damage.damagenum) as bsamount,0 as lyamount,
branch.name as branchname from tb_damage damage inner join
 tb_branch branch on damage.branchid=branch.id group by branch.name,damage.goodsid ) as t
 group by goodsid,branchname) as t on g.id=t.goodsid
下面将对上面的SQL语句进行详细的分析。
(1)查询部门信息的SQL语句如下:
select * from tb_getuse
执行结果如图18.32所示。

图18.32  部门信息
(2)查询部门领用信息的SQL语句如下:
select * from tb_getuse
执行结果如图18.33所示。

图18.33  部门领用信息
(3)通过INNER JOIN子句将部门领用信息表和部门信息表进行关联,具体SQL语句如下:
select * from tb_getuse getuse inner join tb_branch branch on getuse.branchid=branch.id
执行结果如图18.34所示。

图18.34  与部门信息表关联后的部门领用信息
(4)根据部门名称和物资ID对关联后的部门领用信息进行分组并统计部门领用各物资的数量,具体SQL语句如下:
select getuse.goodsid,sum(getuse.number) as lyamount,branch.name as branchname from tb_getuse getuse inner join tb_branch branch on getuse.branchid=branch.id group by branch.name,getuse.goodsid 
执行结果如图18.35所示。
(5)在步骤(4)中的SQL语句的输出结果中添加一个新的列bsamount,该列的值均为0,具体SQL语句如下:
select getuse.goodsid,0 as bsamount,sum(getuse.number) as lyamount,branch.name as branchname from 
tb_getuse getuse inner join tb_branch branch on getuse.branchid=branch.id
 group by branch.name,getuse.goodsid 
执行结果如图18.36所示。
 
         
         图18.35  分组统计后的信息                 图18.36  添加bsamount列后的信息
(6)查询部门报损信息的SQL语句如下:
select * from tb_damage
执行结果如图18.37所示。

图18.37  部门报损信息
(7)通过INNER JOIN子句将部门报损信息表和部门信息表进行关联,具体SQL语句如下:
select * from tb_damage damage inner join tb_branch branch on damage.branchid=branch.id
执行结果如图18.38所示。

图18.38  与部门信息表关联后的部门报损信息
(8)根据部门名称和物资ID对关联后的部门报损信息进行分组并统计部门报损各物资的数量,具体SQL语句如下:
select damage.goodsid,sum(damage.damagenum) as bsamount,branch.name as branchname from 
tb_damage damage inner join tb_branch branch on damage.branchid=branch.id group by 
branch.name,damage.goodsid 
执行结果如图18.39所示。
 
          
        图18.39  分组统计后的信息                  图18.40  添加lyamount列后的信息
(9)在步骤(8)中的SQL语句的输出结果中添加一个新的列lyamount,该列的值均为0,具体SQL语句如下:
select damage.goodsid,sum(damage.damagenum) as bsamount,0 as lyamount,
branch.name as branchname from tb_damage damage inner join  
 tb_branch branch on damage.branchid=branch.id group by branch.name,damage.goodsid 
执行结果如图18.40所示。
(10)通过UNION子句将步骤(5)和步骤(9)的结果合并,具体SQL语句如下:
select getuse.goodsid,0 as bsamount,sum(getuse.number) as lyamount,branch.name as branchname from 
tb_getuse getuse inner join tb_branch branch on getuse.branchid=branch.id group by 
branch.name,getuse.goodsid 
union 
select damage.goodsid,sum(damage.damagenum) as bsamount,0 as lyamount,
branch.name as branchname from tb_damage damage inner join 
tb_branch branch on damage.branchid=branch.id group by branch.name,damage.goodsid 
执行结果如图18.41所示。
(11)对步骤(10)的合并结果进行分组统计,具体SQL语句如下:
 select goodsid,branchname,sum(bsamount) bsamount,sum(lyamount) lyamount from(
select getuse.goodsid,0 as bsamount,sum(getuse.number) as lyamount,branch.name as branchname from 
tb_getuse getuse inner join  tb_branch branch on getuse.branchid=branch.id group by 
branch.name,getuse.goodsid 
union 
select damage.goodsid,sum(damage.damagenum) as bsamount,0 as lyamount,branch.name as branchname 
from tb_damage damage inner join tb_branch branch on damage.branchid=branch.id 
group by branch.name,damage.goodsid 
) as t group by goodsid,branchname
执行结果如图18.42所示。
 
       
           图18.41  合并后的结果                         图18.42  分组统计后的结果
(12)将步骤(10)的分组统计结果与物资信息表tb_goods通过INNER JOIN子句进行关联,具体SQL语句如下:
select g.name,g.spec,g.unit,g.price,t.branchname,t.lyamount,t.bsamount from tb_goods g inner join (
 select goodsid,branchname,sum(bsamount) bsamount,sum(lyamount) lyamount from(
select getuse.goodsid,0 as bsamount,sum(getuse.number) as lyamount,branch.name as branchname from 
tb_getuse getuse inner join tb_branch branch on getuse.branchid=branch.id group by 
branch.name,getuse.goodsid 
union 
select damage.goodsid,sum(damage.damagenum) as bsamount,0 as lyamount,branch.name as branchname 
from tb_damage damage inner join tb_branch branch on damage.branchid=branch.id 
group by branch.name,damage.goodsid 
) as t group by goodsid,branchname
) as t on g.id=t.goodsid
执行结果如图18.43所示。

图18.43  分组统计后的结果
(13)在步骤(12)的分组统计结果的基础上添加一个新的输出列zyamount,该列的值为领用数量减去报损数量,即正在使用数量,具体SQL语句如下:
select g.name,g.spec,g.unit,g.price,t.branchname,t.lyamount,t.bsamount,(t.lyamount-t.bsamount) zyamount 
from tb_goods g inner join (
 select goodsid,branchname,sum(bsamount) bsamount,sum(lyamount) lyamount from(
select getuse.goodsid,0 as bsamount,sum(getuse.number) as lyamount,branch.name as branchname from 
tb_getuse getuse inner join tb_branch branch on getuse.branchid=branch.id group by 
branch.name,getuse.goodsid 
union 
select damage.goodsid,sum(damage.damagenum) as bsamount,0 as lyamount,branch.name as branchname 
from tb_damage damage inner join tb_branch branch on damage.branchid=branch.id 
group by branch.name,damage.goodsid 
) as t group by goodsid,branchname
) as t on g.id=t.goodsid
执行结果如图18.44所示。

图18.44  最后执行结果