基于“Primefaces+Hibernate”框架的企业仓储货位管理系统的技术实现
2021-05-07常学伟
常学伟
(阳煤丰喜肥业(集团)有限责任公司闻喜复肥分公司,山西运城 044402)
0 引言
阳煤丰喜肥业(集团)有限责任公司闻喜复肥分公司拥有两条15万吨高塔复合肥生产线、一条15万吨转鼓造粒生产线,一条5万吨的转鼓造粒生产线,另设有液体肥、水溶肥新型品种肥料生产线,年生产能力达到50万吨,是华北地区最大的复合肥生产企业之一,产品适用于全国不同地域、各种作物的用肥需求。产品年产量大、品类多及仓储区域大等实际情况给公司的仓储管理带来一定难度。
目前,我公司信息化管理方面,在采购、销售、仓储及财务等环节均采用浪潮公司ERP软件,大大减轻了各部门的工作量,并实现与上级集团公司业务的无缝对接。但在实际应用中发现,ERP系统对仓储现场的货位管理不完善,且ERP是桌面软件已投入使用多年,不具备移动端在线查询功能,另货物出入库频繁,产品型号多,造成保管找不到货的情况时有发生,针对这种情况,本文主要采用Java Web框架的primefaces开源类库和hibernate框架开发一个方便在线查询货位、库存数等记录,以此来简化仓储现场货位管理,提高工作效率。
图1 复合肥仓储货位前台查询界面Fig.1 The front desk query interface of compound fertilizer storage space
1 系统设计
本仓储货位管理系统通过“Primefaces+Hibernate”java 框架编程技术,结合Mysql数据库实现。程序运行在阿里云服务器,服务器软件为Tcomat,服务器版本为7.2,数据库为Mysql,数据库版本为5.0。该系统分为前台查询,后台管理及数据库三部分组成。
1.1 前台查询界面设计
前台界面为仓储管理人员提供一个能够查询产品货位的功能,方便通过移动端设备随时查询,主要功能为登录界面、当前库存明细、按配方汇总明细等三个功能。如图1所示。
1.2 后台管理界面设计
后台管理由管理员操作,功能为期初库存、当期产品入库、当期产品出库、当前库存、结账及用户管理等功能。如图2所示。
1.3 数据库表设计
底层数据库采用Mysql来存储数据,分别设计:期初库存表openingStockTable,入库表storageVolumeTable和出库表deliveryVolumnTable、用户表user_manager四个表格。这四个数据表结构如表1-表4。
2 系统业务逻辑分析
图2 复合肥仓储货位后台管理界面Fig.2 The back-end management interface of compound fertilizer storage space
表1 期初库存表OpeningStockTableTab.1 OpeningStockTable
表2 入库表StorageVolumeTableTab.2 StorageVolumeTable storageVolumeTable
2.1 前台、后台登录
登录窗口设置用户名输入框、密码输入框、信息提示、登录按钮等primefaces组件。单击登录按钮后,出现如下几种情况:
(1)当用户名或秘密为空时,信息提示“内容为空,请重新输入”。
(2) 当输入用户名在user_manager数据表中不存在,信息提示“用户不存在,请重新输入”。
(3)当输入的用户名存在,但输入的密码与数据表中密码不一致,信息提示“密码错误,请重新输入”。
(4)当输入用户名和密码均正确,但用户名所对应的用户类型不符合登录类型时,信息提示“输入用户没有登录权限,请联系管理员!”。用户类型设置“前台用户”和“管理员”两种,“前台用户”只允许登录前台查询界面,“管理员”只允许登录后台管理界面。
(5)当输入用户名、密码、用户类型和数据表信息相符时,从登录界面跳转值前台主页面或者后台管理页面。
2.2 后台管理中,期初库存录入、出入库录入
(1)单笔出入库记录明细录入,项目分别是:配方类别、配方名称、仓库名称、货位号、包装袋样式和型号、数量、货物状况等项目手动收入,记录人、记录时间由系统自动录入。
(2)期初产品信息录入,需判断入库产品在是否已经存在,如果存在提示“期初库存已存在记录要输入的记录,无需再进行输入操作!”,如果不存在,则直接插入记录即可。
(3)当期产品入库时,应先判断期初产品库存中是否有相同记录(数量信息除外),如果没有,先在期初表中插入信息,然后再到当期入库表中插入。
(4)期初表中的当期入库总数、当期出库总数和当前库存数根据当期入库表和当期出表中数据结合Hibernate HQL查询中的sum函数和查询条件,在插入或出库完成并在页面导向成功后更新。
(5)产品出库时,应当判断期初表中的当前库存总数和要出库数大小,如果当前库存总数≥要出库数,则在出库表中插入记录,页面导向成功并自动更新期初表中出库总数和当前库存数等。如果要出库的产品不存在,则提示信息“产品不存在”,如果出库数大于当前库存数,则提示信息“要出库数,超库存数”。
2.3 查询功能
(1)分别将期初表、入库表、出库表中的数据明细以表格形式显示在页面上。
(2)当前库存明细以表格形式显示在页面上。
(3)当前库存按照配方分类汇总,以条形图表的形式显示在页面上。
2.4 结账
(1)把期初库存表openingStockTable中的当前库存数currentStock字段赋值给期初库存openingStock字段;
(2)将期初库存表openingStockTable中的当期入库总数storageVolumeSum、当期出库总数deliveryVolumeSum、当前库存数currentStock等三个字段数值清0;
(3)入库表storageVolumeTable和出库表storageVolume Table中的数据清0。
3 技术实现
3.1 开发环境
(1)java软件开发包版本为:JDK7;
(2)开发软件为NetBeans IDE 7.2软件;
表3 出库表StorageVolumeTableTab.3 Outbound table StorageVolumeTable
表4 用户表user_managerTab.4 User table user_manager
(3)数据库使用Mysql5.0;
(4)主要jar包。
1)Primefaces jar包:primefaces3.4.2.jar;
2)JSF jar包:jsf-api.jar、jsf-impl.jar、standard.jar、jstl.jar;
3)Hibernate jar包:hibernate3.jar;
4)MySQL JDBC 驱动程序:mysql-connector-java-5.0.4-bin.jar.
3.2 通过Hibernate创建对象/关系数据映射
因创建多个数据表,操作方法类似,所以下面以创建期初表为例,进行阐述。
(1)根据1.3数据库表的设计,创建持久化 JavaBean类文件,名称为openingStockTable,并根据字段名及类型声明相应的属性,最后设置get和set方法,实例如下:
public class openingStockTable {
public openingStockTable() {
}
private Long id; //编号
private String formulaStyle; //配方类别 尿基、硝基、转鼓等
private String formulaName; //配方名称
......
......
......
public Long getId() {
return id; }
public void setId(Long id) {
this.id = id; }
public String getFormulaStyle() {
return formulaStyle; }
public void setFormulaStyle(String formulaStyle) {
this.formulaStyle = formulaStyle; }
public String getFormulaName() {
return formulaName; }
public void setFormulaName(String formulaName) {
this.formulaName = formulaName;}
......
......
......
//因篇幅有限,上述省略号省略剩余
属性的set和get方法创建。
}
(2)映射配置文件创建。
通过NetBeansIDE开发工具创建映射配置文件,文件名称为openingStockTable.hbm.xml,映射配置文件中将上述Bean文件中的属性与要创建的数据表中的字段建立起映射关系。文件位置放置在WEB-INF/class文件夹下,映射内容如下:
"openingStockTable"> ...... ...... ......
说明:⑴通过class、id和property标签将4.2.1中的JavaBean类与数据库表,类属性与数据库表字段建立起映射关系。⑵上述表中,如果类属性为float类型的,则property标签中的type值应为“float”;类属性为Date日期类型的,则property标签中的type值应为“date”;类属性为String类型的,则property标签中的type值应为“string”。
(3)连接数据库。
通过NetBeansIDE开发工具创建hibernate.cfg.xml文件,文件位置放置在WEB-INF/class文件夹下,内容如下:
mysql://localhost:3306/xyfilems?useUnicode=true&characterEncoding=UTF-8
说明:通过property标签建立数据库连接,并将前面创建的四个数据库表的映射文件进行配置。
(4)创建数据库,并通过java程序自动创建数据表。
使用Hibernate框架,可以让我们以面向对象的思想操作数据库,无需直接操作数据。通过Hibernate框架提供的SchemaExport类,可以在创建好数据库后直接根据上述持久化类、映射文件配置信息直接创建表格。创建一个名称为createDataBaseTable的java主类文件,内容如下:
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
public class createDataBaseTable {
public static void main(String[]args) {
// TODO code application logic here
try {
Configuration cfg = new Configuration().configure();
SchemaExport exporg = new SchemaExport(cfg);
exporg.create(true, true);
} catch (Exception ex) {
} finally {
}}}
说明:运行上述文件后,前面配置的4个数据库表自动创建成功。
3.3 创建HibernateUtil.java工具类
对于在项目业务逻辑层需要与数据库建立连接、终止的部分,这里通过建立一个工具类,方便在后续在项目中调用,内如如下:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
Configuration config = new Configuration().configure();
sessionFactory = config.buildSessionFactory();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession() {
return sessionFactory.openSession();
}
public static void closeSession(Session session) {
if (session != null) {
if (session.isOpen()) {
session.close();
}
}
}
}
3.4 配置项目基础配置文件web.xml
使用NetBeansIDE开发工具创建项目后,在WEB-INF文件夹下会自动创建wen.xml配置文件,配置内容如下:
30
说明:该配置文件指定了primefaces的核心控制器javax.faces.webapp.FacesServlet和项目的默认主页访问路径等信息。
3.5 faces-config.xml文件配置
使用NetBeansIDE开发工具创建faces-config.xml文件,创建后初始文件如下:
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webfacesconfig_2_1.xsd">
该配置文件用于注册Primefaces 受管Bean文件,通过“managed-bean”标签实现注册,另外,Primefaces组件页面之间的导向配置,通过“navigation-rule”标签实现。
3.6 web层的实现
Web层的页面设计通过Primefaces提供的组件完成,因篇幅有限,这里主要将项目中应用较多的组件介绍,其他组件的使用可以参考primefaces参考手册了解。
3.6.1 组件实现联动功能
在项目开发中,有时需要通过选择一个下拉列表项,另外一个下拉列表自动显示子选项,这功能可以通过下拉列表组件的rendered属性、p:ajax组件和valueChange Listener事件来实现。功能实现方法如下:
(1)创建Bean文件,并在faces-config.xml文件中注册。
1)faces-config.xml文件中注册Bean
2)Bean文件代码,下述省略部分为声明的属性设置set和get方法。
package warehouseSystem.productInfoInput;
import java.util.HashMap;
import javax.faces.event.ValueChangeEvent;
import org.primefaces.component.outputlabel.OutputLabel;
import org.primefaces.component.selectonemenu.SelectOneMenu;
public class openingStock_insert {
public openingStock_insert() {
formulaStyleMap.put("尿基", "尿基");
formulaStyleMap.put("硝基", "硝基");
niaojiformulaMap.put("28-6-6", "28-6-6");
niaojiformulaMap.put("24-14-7", "24-14-7");
niaojiformulaMap.put("25-10-5", "25-10-5");
niaojiformulaMap.put("27-14-10", "27-14-10");
xiaojiformulaMap.put("硝15-15-15","硝15-15-15");
xiaojiformulaMap.put("硝15-7-21","硝15-7-21");
xiaojiformulaMap.put("硝16-6-21","硝16-6-21");
}
//配方类型
public String formulaStyleValue;
public String getFormulaStyleValue() {......}
public void setFormulaStyleValue(String formulaStyleValue) {......}
HashMap formulaStyleMap = new HashMap();
public HashMap getFormulaStyleMap() {......}
public void setFormulaStyleMap(HashMap formulaStyleMap) {......}
//配方选项赋值
HashMap niaojiformulaMap = new HashMap();
public HashMap getNiaojiformulaMap(){......}
public void setNiaojiformulaMap(HashMap niaojiformulaMap) {......}
//配方选项赋值
HashMap xiaojiformulaMap = new HashMap();
public HashMap getXiaojiformulaMap() {......}
public void setXiaojiformulaMap(HashMap xiaojiformulaMap) {......}
OutputLabel oplFormulaName = new OutputLabel();
public OutputLabel getOplFormulaName(){......}
public void setOplFormulaName(OutputLabel oplFormulaName) {......}
SelectOneMenu somNiaoji = new SelectOneMenu();
public SelectOneMenu getSomNiaoji() {......}
public void setSomNiaoji(SelectOneMenu somNiaoji){......}
SelectOneMenu somxiaoji = new SelectOneMenu();
public SelectOneMenu getSomxiaoji() {......}
public void setSomxiaoji(SelectOneMenu somxiaoji){......}
//当触发ValueChange事件时,会根据选项值执行相应的动作。
public void changeFormulaNameEvent(ValueChange Event e) {
//获取下拉选项的值
Object countryName = e.getNewValue();
//this.setCities(this.getChinaMapCity());
if (countryName.equals("尿基")) {
oplFormulaName.setRendered(true);
somNiaoji.setRendered(true);
somxiaoji.setRendered(false);
} else if (countryName.equals("硝基")) {
oplFormulaName.setRendered(true);
somNiaoji.setRendered(false);
somxiaoji.setRendered(true);
}
}
}
(2)使用NetBeansIDE开发工具创建xhtml网页文件,代码如下:
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core">
说明:上述功能为选择id属性为“formulaStyleId”的p:selectOneMenu组件的值,触发valueChangeListener事件,p:ajax组件的ajax属性刷新form范围,另外两个组件会根据选择的值,判断是否显示和显示子选项。
3.6.2 p:dataTable表格组件
(1)组件属性(表5)。
(2)从数据库中调用数据,并见数据通过p:dataTable表格组件显示出来,可以通过hibernate将数据复制给List对象,然后再将List对象值赋值给ListDataModel数据模型,最后在数据表格中即可显示。
1)在受控Bean文件中,声明ListDataModel数据模型。
public ListDataModel allWarehouseDataModel = new ListDataModel();
public ListDataModel getAllWarehouseDataModel() {
return allWarehouseDataModel;
}
public void setAllWarehouseDataModel(ListDataModel allWarehouseDataModel) {
this.allWarehouseDataModel = allWarehouseData Model;
}
2)在受控Bean文件中,通过hibernate调用数据库数据,并将数据赋值给ListDataModel对象。
Session session = null;
try {
session = HibernateUtil.getSession();
session.beginTransaction();
Query query = session.createQuery(" from openingStockTable order by formulaStyle");
List names = query.list();
allWarehouseDataModel.setWrappedData(names);
} catch (Exception ex) {
} finally {
HibernateUtil.closeSession(session);
}
3)在xhtml网页文件中,通过p:dataTable表格组件显示数据。
rows="8" paginatorPosition="bottom" paginator AlwaysVisible="false" emptyMessage="无内容"paginatorTemplate="{CurrentPageReport} {FirstPage Link} {PreviousPageLink} {PageLinks} {NextPageLink}{LastPageLink}">
根据需要显示的数据,在p:dataTable组件中,增加p:column组件,即可增加数据表的列数。p:dataTable组件的value值绑定的就是前面已经创建好的ListDataModel对象。
3.6.3 p:barChart条形图表
PrimeFaces框架共提供了有100多个支持AJAX的JSF组件。其中,图表组件就提供了饼图、折线图、条形图、圈图、气泡图等多个图表组件供开发者直接使用,功能丰富,大大提高了开发效率。这里介绍项目中使用的条形图表的应用。
要将数据在p:barChart条形图表组件中显示,需要调用primefaces类库中的CartesianChartModel图表模型和ChartSeries类对象。首先,通过hibernate从数据库中调取数据,并将数据赋值给Object[]数组,然后再将对象数组值赋值给ChartSeries对象,最后再将ChartSeries对象值赋值给CartesianChartModel图表模型。具体实现代码如下:
(1)在受控Bean文件中,声明CartesianChartModel数据模型和ChartSeries对象。
CartesianChartModel openingStockChartModelNiaoji= new CartesianChartModel();
public CartesianChartModel getOpeningStockChart ModelNiaoji() {
return openingStockChartModelNiaoji;
}
public void setOpeningStockChartModelNiaoji(CartesianChartModel openingStockChartModelNiaoji) {
this.openingStockChartModelNiaoji = openingStock ChartModelNiaoji;
}
ChartSeries openingStockCSNiaoji = new ChartSeries();
表5 p:dataTable组件属性值Tab.5 p:dataTable component attribute values
public ChartSeries getOpeningStockCSNiaoji() {
return openingStockCSNiaoji;
}
public void setOpeningStockCSNiaoji(ChartSeries openingStockCSNiaoji) {
this.openingStockCSNiaoji = openingStockCSNiaoji;
}
(2)在受控Bean文件中的无参构造函数中,通过hibernate调用数据库数据,并将数据赋值给ChartSeries对象,然后再将ChartSeries对象值赋值给CartesianChartModel数据模型。
Session session = null;
try {
session = HibernateUtil.getSession();
session.beginTransaction();
Query query = session.createQuery("select formulaName,sum(currentStock) from openingStockTable where formulaStyle= :fs group by formulaName");
query.setString("fs", "尿基");
List li = query.list();
Iterator ite = li.iterator();
while (ite.hasNext()) {
Object[]obj = (Object[]) ite.next();
openingStockCSNiaoji.set(obj[0],Float.valueOf(obj[1].toString()));
}
openingStockChartModelNiaoji.addSeries(opening StockCSNiaoji);
} catch (Exception ex) {
//session.getTransaction().rollback();
} finally {
HibernateUtil.closeSession(session);
}
(3)在xhtml网页文件中,通过p:barChart组件将数据以条形图的形式显示出来。
p:barChart组件条形图表组件的value值为前面创建的CartesianChartModel对象。
4 结语
本文主要介绍了采用“Primefaces+Hibernate”框架实现企业仓储管理货位管理项目的技术实现。通过Prime faces提供的丰富组件和采用Hibernate面向对象的数据操作,使得项目开发效率大大提高。