小型仓库管理系统的详细设计实现.doc_第1页
小型仓库管理系统的详细设计实现.doc_第2页
小型仓库管理系统的详细设计实现.doc_第3页
小型仓库管理系统的详细设计实现.doc_第4页
小型仓库管理系统的详细设计实现.doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

小型仓库管理系统的详细设计及实现1. 系统设计概述(1)问题域部分,设计构造一组为底层应用建立模型的类和对象,细化分析结果;由建立数据对象部分实现。(2)人机交互部分,设计一组有关类接口视图的用户模型的类和对象,设计用户界面;由建立商品数据维护界面部分实现。(3)任务管理部分,确定系统资源的分配,设计用于系统中类的行为控制的对象/类;由建立商品类别显示模型和商品类型模型部分以及建立商品数据维护界面部分共同实现。(4)数据管理部分,确定持久对象的存储,将对象转换成数据库记录或表格;由连接数据库和建立商品数据访问对象部分实现。2. 连接数据库要通过Java访问数据库,必须要使用JDBC(Java Data Base Connectivity,java数据库连接),访问不同的数据库,采用的JDBC驱动程序也不同。连接Access采用Jdbc-odbc桥的方式比较方便,不需要引入额外的驱动程序包。主流的数据库都提供了专门的JDBC驱动,如ORCALE、Sql Server、Sybase等等,对于微软的Access和Excel以及其他的一些小型的桌面数据库,可以通过JDBC-ODBC桥接的方式来访问。通过编码,我们不需要在环境中配置ODBC数据源,就可以直接访问这些小型桌面数据库。在应用系统中,数据库的连接参数一般都是写在配置文件当中,以防止数据库的属性的变化导致程序的修改。对于本任务来说,Access是桌面数据库,我们需要知道的只是Access数据库文件的路径,因此我们可以将Access数据库文件拷贝到发布路径下,从而可以通过编码获得数据库文件路径,而不需要使用配置文件。package test.sample.dao;import .URL;import java.sql.Connection;import java.sql.DriverManager;public class DaoFactory static public Connection getConnection() throws ExceptionClass.forName(sun.jdbc.odbc.JdbcOdbcDriver); /加载数据库驱动 URL dbUrl =DaoFactory.class.getClassLoader().getResource(Mystock.mdb);String dbPath=dbUrl.getPath(); /通过Java的类加载机制,获得数据库文件路径if (dbPath.charAt(0)=/) /去掉路径的第一个字符/dbPath=dbPath.substring(1);String url = jdbc:odbc:driver=Microsoft Access Driver (*.mdb);DBQ=+dbPath; Connection con = DriverManager.getConnection(url, sa, ); return con;Class.forName方法的作用是通过类的完整路径名获得一个类的实例,在本例子中的作用是加载我们要使用的数据库驱动。在使用DriverManager获得数据库连接前,必须通过此语句加载数据库驱动。ClassLoader类负责管理Java编译后代码的加载,因此能够获取class文件的加载路径,也就是应用的发布路径。我们把数据库文件放到发布路径下(即class文件所在路径),即可以通过ClassLoader类的getResource方法获得该文件的绝对路径。由于获得的绝对路径的第一个字符是“/”,这是为了兼容不同的操作系统而导致的,这个符号在Access的数据库路径上是不合法的,需要去掉。通过数据库url,提供数据库的驱动描述,以及数据库的路径,就可以使用DriverManager类来获得数据库连接。3. 建立商品数据访问对象从数据库中提取数据,以及向数据库中插入记录和删除数据,都必须使用SQL语句来完成。因此数据访问对象的方法,实际上就是通过Java数据访问对象,在数据库数据和数据对象之间进行转换。在数据库的访问中,我们需要用到几个数据访问对象:1java.sql.Connection:用来获得数据库连接。2java.sql.PreparedStatement和java.sql.Statement:都可以用来执行SQL语句。其中PreparedStatement的功能较强,SQL 语句被预编译并且存储在 PreparedStatement 对象中。然后可以使用此对象高效地多次执行该语句。PreparedStatement可以设置set方法设置参数。以下是一个设置参数的示例中,con 表示一个活动连接: PreparedStatement pstmt = con.prepareStatement(UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?); pstmt.setBigDecimal(1, 2000.00) ; pstmt.setInt(2, 100) ; pstmt.excuteUpdate();SQL语句中需要赋值的部分可以用?代替,然后通过set方法来设置参数。由于设计参数时不同的类型方法也不同,能够很好的处理不同的类型。例如在设置日期型的参数时,可以直接通过setDate方法设置参数,而如果通过SQL语句的字符串拼写,则必须对日期进行格式化。对于复杂的Insert、update和delete的SQL语句,以及需要多次执行而参数不同的SQL语句,使用PreparedStatement具有明显优势。3java.sql.ResultSet:从数据库库提取后的数据保存在ResultSet中,ResultSet提供的getter方法能够方便的返回记录集中的数据。程序代码设计如下:package test.sample.dao;import java.sql.*;import java.util.ArrayList;import java.util.List;import test.sample.bean.Product;import test.sample.bean.ProductType;public class ProductDao /提取商品数据,并转换为商品对象,存储到列表中public static List getProductList() throws ExceptionConnection conn=DaoFactory.getConnection();tryStatement st = conn.createStatement();String sql=select * from Product;ResultSet rs = st.executeQuery(sql);List list=new ArrayList();while(rs.next()Product p=new Product();p.setId(rs.getInt(ID);p.setName(rs.getString(NAME);p.setType(rs.getInt(TYPE);p.setCountInBox(rs.getString(COUNT_IN_BOX);p.setPrice(rs.getFloat(PRICE);p.setStock(rs.getInt(STOCK);list.add(p);rs.close();st.close();return list;finallyconn.close();/将一个商品对象插入到数据库public static Product InsertProduct(Product p) throws Exception Connection conn=DaoFactory.getConnection();tryString sql=INSERT INTO Product(NAME,TYPE,COUNT_IN_BOX,PRICE,STOCK) VALUES(?,?,?,?,?);PreparedStatement ps=conn.prepareStatement(sql); ps.setString(1,p.getName();ps.setInt(2,p.getType();ps.setString(3,p.getCountInBox();ps.setFloat(4,p.getPrice();ps.setInt(5,p.getStock();ps.executeUpdate();Statement st=conn.createStatement();ResultSet rs=st.executeQuery(select max(ID) from Product);rs.next(); int id = rs.getInt(1); p.setId(id);rs.close();st.close();ps.close();return p; finallyconn.close();/将一个商品对象插入到数据库public static Product updateProduct(Product p) throws Exception Connection conn=DaoFactory.getConnection(); try String sql=UPDATE Product set NAME=?,TYPE=?,COUNT_IN_BOX=?,PRICE=?,STOCK=? where ID=?;PreparedStatement ps=conn.prepareStatement(sql); ps.setString(1,p.getName();ps.setInt(2,p.getType();ps.setString(3,p.getCountInBox();ps.setFloat(4,p.getPrice();ps.setInt(5,p.getStock();ps.setInt(6,p.getId();ps.executeUpdate();ps.close();return p;finallyconn.close();/删除一个商品记录public static boolean deleteProduct(int id) throws ExceptionConnection conn=DaoFactory.getConnection();tryString sql=delete from Product where ID=+id;Statement ps=conn.createStatement();boolean b = ps.execute(sql);ps.close();return b;finallyconn.close();/获取商品类型数据,并转换为商品类型对象,存储到列表public static List getProductTypeList() throws ExceptionConnection conn=DaoFactory.getConnection();tryStatement st = conn.createStatement();String sql=select * from ProductType;ResultSet rs = st.executeQuery(sql);List list=new ArrayList();while(rs.next()ProductType pt=new ProductType();pt.setId(rs.getInt(TYPE_ID);pt.setName(rs.getString(TYPE_NAME);pt.setRemark(rs.getString(REMARK);list.add(pt);rs.close();st.close();return list;finallyconn.close();通过上面的代码我们可以看到,从ProductDao调用方法的对象不需要关系数据库,而只需要知道Product对象即可,无论我们如何修改“商品”数据的存储方法,都不会影响访问对象。也就是说,我们通过ProductDao对象将对商品表数据的访问完全的封装了。访问商品数据的对象甚至不知道商品数据是保存在什么样的数据库当中。这就是面向对象设计的重要特性封装。ProductDao对象提供了“商品”数据的提取、插入、删除方法,提供了商品类别的提取方法。事实上,这不是数据操作的全部,所有涉及商品的数据库操作,都可以放到ProductDao对象中,如修改商品的名称,统计商品的库存等等。4. 建立数据对象数据对象作为应用程序的数据载体,能够用于数据加工和数据传递,同时由于数据对象是无状态的,因此数据对象的使用能够应用实现更加地灵活。数据对象(JavaBean)是一种特殊的对象,特殊的是在类的方法命名上遵守以下规则: 1如果类的成员变量的名字是xxx,那么为了更改或获取成员变量的值,即更改或获取属性,在类中可使用两个方法: getXxx(),用来获取属性;xxx;setXxx(),用来修改属性xxx.。 2 对于boolean类型的成员变量,即布尔逻辑类型的属性,允许使用is代替上面的get。 3类中方法的访问属性都必须是public的。 4类中如果有构造方法,那么这个构造方法也是public的并且是无参数的。事实上,这种方式是面向对象设计的一个理念,即封装。通过get和set 方法,将对象的外在表现和内部实现分离,从而为对象的修改和重用提供良好的基础。例如:一个方法getName,它的作用是返回对象的名字,作为访问者无需知道这个名字是如何存储的,只需调用方法访问即可。package test.sample.bean;/* * 商品对象 */public class Product private int id;/商品的唯一标识private String name; /商品的名称private int type;/商品的类型内码private String countInBox; /每箱数量private float price;/商品的价格private int stock; /库存数量public int getId() return id;public void setId(int id) this.id = id;public String getName() return name;public void setName(String name) = name;public int getType() return type;public void setType(int type) this.type = type;public float getPrice() return price;public void setPrice(float price) this.price = price;public String getCountInBox() return countInBox;public void setCountInBox(String countInBox) this.countInBox = countInBox;public int getStock() return stock;public void setStock(int stock) this.stock = stock;我们可以看到,上面的两个数据对象中,都是通过get和set方法对私有属性进行封装。那么,不使用get 和set方法,直接将属性作为公开属性不行吗?单从程序访问的角度没有问题,我们可以直接访问公开属性,但同时也破坏了数据对象的封装性。更为重要的是,数据对象这种形式已经广泛的为业界所承认,成为一种规则,绝大部分的开源软件通过get和set这种形式来访问数据,例如Hibernate,spring。事实上,这种形式不仅仅在java中使用,在主流的面向对象语言中,都采用了这种形式。5. 建立商品列表显示模型和商品类型模型为了能够将数据对象列表能够以表格(table)的形式进行显示,我们需要为表格显示控件JTable提供一个数据来源。实现一个AbstractTableModel,能够为JTable控件提供数据,将商品对象列表以表格的形式进行显示。在Java swing中以表格形式显示数据的标准控件是JTable,一般的情况下,数据以对象列表或者对象数组的形式存储,表格的每一行显示一个对象的信息,表格的每一列显示对象某个属性的信息。为了能够方便的使用JTable,Java提供了专门支持它的数据模型TableModel。TableModel负责将数据整理为JTable显示所需要的形式,是介于基础数据和显示控件之间的代理。在创建JTable时,可以采用带参数的创建方法,将TableModel作为参数传递给JTable。JTable的数据显示是通过TableModel进行驱动的,因此修改TableModel中的数据,能够通过调用方法刷新JTable的数据显示。为了更加方便的处理数据和数据的显示,我们需要从AbstractTableModel类继承,实现自己的TableModel类。AbstractTableModel是一个抽象数据类型,我们有三个方法必须实现: public int getColumnCount() / 获得要显示的数据的列数public int getRowCount() / 获得要显示的数据的行数public Object getValueAt(int row, int col) / 获得一个单元格的数据以上三个方法的实现可以根据原始数据和显示需求来实现,例如getColumnCount可以根据需要显示的属性的个数确定,getRowCount可以通过数据记录的个数确定。为了支持对数据的修改操作,我们还可以在TableModel中添加一些数据修改的方法。package test.sample.model;import java.util.ArrayList;import java.util.List;import javax.swing.table.AbstractTableModel;import test.sample.bean.Product;import test.sample.dao.ProductDao;public class ProductModel extends AbstractTableModel private List pList=new ArrayList();public void loadData() throws ExceptionpList = ProductDao.getProductList();/列标题String headers = 商品内码, 商品名称, 商品类型, 单位数量, 价格, 库存;/获得列数public int getColumnCount() return headers.length;/获得行数public int getRowCount() return pList.size();/获得一个单元格的数据public Object getValueAt(int row, int col) if (row=pList.size() return ;Product p = (Product) pList.get(row);switch (col) case 0:return new Integer(p.getId();case 1:return p.getName();case 2:return ProductTypeEnum.getTypeName(p.getType();case 3:return p.getCountInBox();case 4:return new Float(p.getPrice();case 5:return new Integer(p.getStock();return ;public Product getProduct(int row)return (Product) pList.get(row);/获得列的名字Overridepublic String getColumnName(int col) return headerscol;/添加一个商品对象public void addProduct(Product p) throws ExceptionProductDao.InsertProduct(p);pList.add(p);this.fireTableRowsInserted(pList.size()-1, pList.size()-1);/更新一个商品对象public void updateProduct(int index,Product p) throws Exceptionif (index=pList.size() return ;ProductDao.updateProduct(p);pList.set(index, p);this.fireTableRowsUpdated(index, index);/删除一个商品对象public void deleteProduct(int index) throws Exceptionif (index=pList.size() return ;Product p1=getProduct(index);ProductDao.deleteProduct(p1.getId();pList.remove(index);this.fireTableRowsDeleted(index, index);ProductModel扩展类AbstractTableModel类,以从数据库提出的对象列表作为数据源。并根据数据列表信息实现了基类的三个虚方法: getRowCount()、getColumnCount()、 getValueAt(int row, int column); 为了支持数据的增加、删除和修改功能,ProductModel还实现了三个方法:1addProduct(Product p):添加一个商品信息。2updateProduct(int index,Product p):更新某行的商品信息。3deleteProduct(int index):删除某行的商品信息。以上三个方法直接调用数据库操作对象的方法,进行数据的添加、删除和修改,数据库修改成功后,修改显示列表,并调用方法fireTableRowsInserted 、fireTableRowsUpdated、 fireTableRowsDeleted ,激活JTable的显示更新。另外、对于商品类型属性,在商品对象中保存的是类型的内码,而显示的时候,需要显示类型的名称,在这种情况下,我们需要做通过商品类别模型获得类型名称。商品表的商品类别保存的是商品类别内码,或者说,商品类别内码是商品表的一个外键。类别表保存了所有商品类别的信息,包括类别ID,类别名称和类别描述三个字段。虽然商品表中使用类别ID记录商品的类别,但是在列表中显示的时候,需要显示给用户商品类别的类别名称。在新增商品信息时,也需要将商品类别名称做成下拉列表,在列表中选择商品类别,同时在商品对象中要保存的却是类别ID。以上的情况都要求一个对象来管理商品类别中类别ID和类别名称的映射关系。作为商品的关联信息,商品类别的在商品表中存储时使用类别ID,而展示时总是展示类别名称,因此通过类别ID获得类别名称,以及通过类别名称获得类别ID的功能是必须的。package test.sample.model;import java.util.HashMap;import java.util.List;import java.util.Map;import test.sample.bean.ProductType;import test.sample.dao.ProductDao;public class ProductTypeEnum static private Map map = null;static private Map nameMap = null;static private String names;static private List dataList = null;private static List getDataList() if (dataList = null) try dataList = ProductDao.getProductTypeList(); catch (Exception e) e.printStackTrace();return dataList;static public String getTypeName(int type) if (map = null) map = new HashMap();List list = getDataList();for (int i = 0; i list.size(); i+) ProductType pt = (ProductType) list.get(i);map.put( + pt.getId(), pt);ProductType p = (ProductType) map.get( + type);if (p != null)return p.getName();elsereturn ;static public int getNameId(String name) if (nameMap = null) nameMap = new HashMap();List list = getDataList();for (int i = 0; i list.size(); i+) ProductType pt = (ProductType) list.get(i);nameMap.put(pt.getName(), pt);ProductType p = (ProductType) nameMap.get(name);if (p != null)return p.getId();elsereturn -1;public static String getNames() if (names = null) List list = getDataList();names = new Stringlist.size();for (int i = 0; i = 0) Integer pId = (Integer) jt.getValueAt(index, 0);String pName = (String) jt.getValueAt(index, 1);int i = JOptionPane.showConfirmDialog(null,确定要删除商品 + pName + ?, 标题,JOptionPane.YES_NO_OPTION); / 弹出确认对话框if (i = JOptionPane.YES_OPTION)try / 删除数据库记录pm.deleteProduct(index); / 删除显示记录 catch (Exception e1) e1.printStackTrace(););popup.add(item);jt.addMouseListener(new MouseAdapter() / 鼠标右键监听匿名内部类public void mouseReleased(MouseEvent event) final int row = jt.rowAtPoint(event.getPoint();if (row != -1) jt.setRowSelectionInterval(row, row); / 高亮选择右键点击的行if (event.isPopupTrigger()popup.show(event.getComponent(), event.getX(),event.getY(););/ 初始化录入控件public void iniInsertPanel() throws Exception JLabel jl1 = new JLabel();jl1.setText(商品名称);jl1.setBounds(10, 10, 60, 20);jp1.add(jl1);jxt1 = new JTextField(10);jxt1.setBounds(75, 10, 200, 20);jp1.add(jxt1);JLabel jl2 = new JLabel();jl2.setText(商品类型);jl2.setBounds(285, 10, 60, 20);jp1.add(jl2);jcb1 = new JComboBox(ProductTypeEnum.getNames();jcb1.setBounds(350, 10, 100, 20);jp1.add(jcb1, BorderLayout.EAST);JLabel jl3 = new JLabel();jl3.setText(单位数量);jp1.add(jl3);jl3.setBounds(10, 40, 60, 20);jxt2 = new JTextField(6);jxt2.setBounds(75, 40, 80, 20);jp1.add(jxt2);JLabel jl4 = new JLabel();jl4.setText(单价);jl4.setBounds(160, 40, 60, 20);jp1.add(jl4);jft1 = new JFormattedTextField();jft1.setColumns(5);jft1.setBounds(195, 40, 80, 20);jp1.add(jft1);JLabel jl5 = new JLabel();jl5.setText(库存);jl5.setBounds(310, 40, 40, 20);jp1.add(jl5);jft2 = new JFormattedTextField();jft2.setColumns(5);jft2.setBounds(350, 40, 100, 20);jp1.add(jft2);buttonInsert = new JButton(添加);buttonInsert.setBounds(460, 10, 60, 50);/ 添加按钮点击事件buttonInsert.addActionListener(new ActionListener() public void actionPerformed(ActionEvent event) try doInsertProduct(); catch (Exception e) e.printStackTrace(););jp1.add(buttonInsert);buttonUpdate = new JButton(修改);buttonUpdate.setBounds(530, 10, 60, 50);/ 修改按钮点击事件buttonUpdate.addActionListener(new ActionListener() public void actionPerformed(ActionEvent event) try doUpdateProduct(); catch (Exce

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论