java零基础Ⅲ-- 6.满汉楼项目

连接视频



需求说明

要完成的满汉楼项目说明

满汉楼项目功能多,界面复杂,设及到复杂的awt 和 swing 技术 和事件编程,做如下调整

1、去掉界面和事件处理(工作中使用很少),使用控制台界面

2、完成满汉楼项目的 登录、订座、点餐和结账、查看账单 等功能

3、提示:在实际工作中,独立完成项目的新功能非常重要,这是锻炼编程能力和思想的重要途径



界面设计

用户登录

在这里插入图片描述


显示餐桌状态

在这里插入图片描述


预定

在这里插入图片描述


显示菜品

在这里插入图片描述


点餐

在这里插入图片描述


查看账单

在这里插入图片描述


结账

在这里插入图片描述



功能实现

准备工具类 Utility,提高开发效率,并搭建 项目的整体结构

项目结构:

在这里插入图片描述

添加依赖包到项目中:

在这里插入图片描述

在实际开发中,公司都会通过相应的工具类和开发库,可以提高开关效率

Utility工具类

package com.zzpedu.mhl.utils;

import java.util.Locale;
import java.util.Scanner;

/**
 * 工具类的作用:
 *  处理各种情况用户的输入,并且能够按照程序员的需求,得到用户的控制台输入
 */
public class Utility {
    //静态属性...
    private static Scanner scanner = new Scanner(System.in);

    /**
     * 功能:读取键盘输入的一个菜单选项,值:1--6的范围
     * @return 1--6
     */
    public static char readMenuSelection(){
        char c;
        for(; ;){
            String str = readKeyBoard(1,false);//包含一个字符串
            c = str.charAt(0);//将字符串转换成字符char类型
            if(c != '1' && c != '2' &&
                    c != '3' && c != '4' && c !=  '5' && c != '6'){
                System.out.println("选择错误,请重新输入(1-6):");
            }else break;
        }
        return c;
    }

    /**
     * 功能:读取键盘输入的一个字符
     * @return 一个字符
     */
    public static char readChar(){
        String str = readKeyBoard(1,false);//就是一个字符
        return str.charAt(0);
    }

    /**
     * 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值
     * @param defaultValue 指定的默认值
     * @return 默认值或者输入的字符
     */
    public static char readChar(char defaultValue){
        String str = readKeyBoard(1,true);//要么是空字符串,要么就是一个字符
        return (str.length() == 0) ? defaultValue : str.charAt(0);
    }

    /**
     * 功能:读取键盘输入的整型,长度小于2
     * @return
     */
    public static int readInt(){
        int n = 0;
        for (; ;){
            String str = readKeyBoard(10,false);//一个整数,长度小于10位
            try {
                n = Integer.parseInt(str);//将字符串转成整数
                break;
            }catch (NumberFormatException e){
                System.out.println("数字输入错误,请重新输入:");
            }
        }
        return n;
    }

    /**
     * 功能:读取键盘输入的 整数或者默认值,如果直接按回车,则返回指定的默认值,否则返回整数
     * @param defaultValue 指定的默认值
     * @return 整数或者默认值
     */
    public static int rendInt(int defaultValue){
        int n;
        for (; ;){
            String str = readKeyBoard(10,true);
            if(str.equals("")){
                return defaultValue;
            }

            //异常处理...
            try {
                n = Integer.parseInt(str);
                break;
            }catch (NumberFormatException e){
                System.out.println("数字输入错误,请重新输入:");
            }
        }
        return n;
    }

    /**
     *  功能:读取键盘输入的指定长度的字符串
     * @param limit 限制的长度
     * @return 指定长度的字符串
     */
    public static String readString(int limit){
        return readKeyBoard(limit,false);
    }

    /**
     * 功能:读取键盘输入的指定长度的字符串或者默认值,如果直接回车,则返回给定的默认值
     * @param limit 限制的长度
     * @param defaultValue 指定的默认值
     * @return 指定长度的字符串
     */
    public static String readString(int limit,String defaultValue){
        String str = readKeyBoard(limit,true);
        return str.equals("") ? defaultValue : str;
    }

    /**
     *  功能:读取键盘输入的确定选项,Y或者N
     *  将小的功能,封装到一个方法中
     * @return Y或N
     */
    public static char readConfirmSelection(){
        System.out.print("确认是否预定(Y/N): ");
        char c;
        for(; ;){//无限循环
            //在这里,将接受到字符,转成大写字母
            //y => Y n => N
            String str = readKeyBoard(1,false).toUpperCase(Locale.ROOT);
            c = str.charAt(0);
            if(c == 'Y' || c == 'N'){
                break;
            }else {
                System.out.print("选择错误,请重新输入(Y/N): ");
            }
        }
        return c;
    }

    /**
     * 功能:读取键盘输入的字符串指定长度
     * @param limit 指定长度
     * @param flag 状态
     *             true:代表可以为空字符串
     *             false:不能为空字符串
     * @return 字符串
     */
    private static String readKeyBoard(int limit, boolean flag) {
        String str = "";
        do {
            //nextLine():
            //1.以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
            //2.可以获得空白。
            str = scanner.nextLine();
            if(str.length() == 0){
                if(flag) return str;//如果flag=true,可以返回空字符串
                else continue;//如果flag=false,不接受空字符串,必须输入内容
            }
            //如果用户输入的内容大于了 limit ,就提示输入
            //如果用户输入的内容 >0 <= limit,就返回退出
            if (str.length() < 1 || str.length() > limit){
                System.out.print("输入长度(不能大于" + limit +")错误,请重新输入:");
            }else {
                return str;
            }
        }while (true);
    }
}

druid数据库连接池的工具类

package com.zzpedu.mhl.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 基于druid数据库连接池的工具类
 */
public class JDBCUtilsByDruid {

    private static DataSource dataSource;

    //在静态代码块完成 dataSource初始化
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src//druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //编写getConnection方法
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    //关闭连接,强调:在数据库连接池技术中,close 不是真的断掉数据库连接
    //而是把使用的Connection放回连接池
    public static void close(ResultSet set, Statement statement,Connection connection){
        //判断是否为null
        try {
            if(set != null){
                set.close();
            }
            if(statement != null){
                statement.close();
            }
            if(connection != null){
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

druid配置文件druid.properties 存放在 src目录下

#key=value
# 驱动名称
driverClassName=com.mysql.jdbc.Driver
# url数据库地址
url=jdbc:mysql://localhost:3306/mhl?useUnicode=true&characterEncoding=utf8&serverTimezone=PRC&useSSL=false&rewriteBatchedStatements=true
# 用户名
username=root
# 密码
password=123456
#initial connection Size
# 初始化连接数
initialSize=10
#min idle connection size
# 最小连接数(空闲数)
minIdle=5
#max active connection size
# 最大连接数
maxActive=50
#max wait time (5000 mil seconds)
# 最大等待时间5s(超时时间)
maxWait=5000

BasicDAO,是其他DAO的父类

package com.zzpedu.mhl.dao;


import com.zzpedu.mhl.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * 开发BasicDAO,是其他DAO的父类
 */
public class BasicDAO<T> {//泛型指定具体类型

    private QueryRunner qr = new QueryRunner();

    //开发通用的dml方法,针对任意的表
    public int update(String sql, Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            int update = qr.update(connection, sql, parameters);
            return update;
        } catch (SQLException e) {
            throw new RuntimeException(e);//将编译异常 转换 运行异常,抛出
        }finally {
            JDBCUtilsByDruid.close(null,null,connection);
        }
    }

    /**
     *  返回多个对象(即查询结果是多行),针对任意表
     * @param sql sql语句,可以有 ?
     * @param clazz 传入一个类的Class对象 比如 Actor.class
     * @param parameters 传入 ? 的具体值,可以是多个
     * @return 根据Actor.class 返回对应的 ArrayList 集合
     */
    public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);//将编译异常 转换 运行异常,抛出
        }finally {
            JDBCUtilsByDruid.close(null,null,connection);
        }
    }

    //查询单行结果的通用方法
    public T querySingle(String sql, Class<T> clazz, Object... parameters ){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);//将编译异常 转换 运行异常,抛出
        }finally {
            JDBCUtilsByDruid.close(null,null,connection);
        }
    }

    //查询单行但列的方法,即返回单值的方法
    public Object queryScalar(String sql, Object... parameters ){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new ScalarHandler(), parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);//将编译异常 转换 运行异常,抛出
        }finally {
            JDBCUtilsByDruid.close(null,null,connection);
        }
    }
}

显示主菜单,二级菜单和退出系统功能

在这里插入图片描述

主界面:

package com.zzpedu.mhl.view;

import com.zzpedu.mhl.utils.Utility;

/**
 * 这是主界面
 */
public class MHLView {

    //控制是否退出菜单
    private boolean loop = true;
    //接收用户的输入
    private String key = "";

    public static void main(String[] args) {
        new MHLView().mainMenu();
    }

    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
            System.out.println("\t\t 1 登录满汉楼");
            System.out.println("\t\t 2 退出满汉楼");
            System.out.print("请输入你的选择: ");
            key = Utility.readString(1);
            switch (key){
                case "1":
                    System.out.print("输入员工号: ");
                    String id = Utility.readString(50);
                    System.out.print("输入密  码: ");
                    String pwd = Utility.readString(50);
                    //到数据库去判断【一会写】
                    if("123".equals(pwd)){
                        System.out.println("==============登录成功==============\n");
                        //显示二级菜单,这里二级菜单是循环操作,所以做成while
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单==============");
                            System.out.println("\t\t 1 显示餐桌状态");
                            System.out.println("\t\t 2 预定餐桌");
                            System.out.println("\t\t 3 显示所以菜品");
                            System.out.println("\t\t 4 点餐服务");
                            System.out.println("\t\t 5 查看账单");
                            System.out.println("\t\t 6 结账");
                            System.out.println("\t\t 9 退出");
                            System.out.print("请输入你的选择: ");
                            key = Utility.readString(1);
                            switch (key){
                                case "1":
                                    System.out.println("显示餐桌状态");
                                    break;
                                case "2":
                                    System.out.println("预定餐桌");
                                    break;
                                case "3":
                                    System.out.println("显示所以菜品");
                                    break;
                                case "4":
                                    System.out.println("点餐服务");
                                    break;
                                case "5":
                                    System.out.println("查看账单");
                                    break;
                                case "6":
                                    System.out.println("结账");
                                    break;
                                case "9":
                                    loop = false;
                                    break;
                                default:
                                    System.out.println("你输入有误,请求重新输入");
                            }
                        }

                    }else {
                        System.out.println("==============登录失败==============");
                    }
                    break;
                case "2":
                    loop = false;
                    break;
                default:
                    System.out.println("你输入有误,请求重新输入");
            }
        }
        System.out.println("您退出了满汉楼系统~");

    }
}

创建员工表信息

-- 创建满汉楼数据库
create database mhl;

-- 创建表 employee 表 (主键id,empId,name,pwd,job等,如果还有需要可以自己加字段)
create table employee(
		id int primary key AUTO_INCREMENT, # 自增
		empId varchar(50) unique null null default '', # 员工号
		pwd char(32) null null default '', # 密码md5
		`name` varchar(50) null null default '', # 姓名
		job varchar(50) null null default '' # 岗位
)charset=utf8;

# 添加测试数据
insert into employee values (null,'6668612',md5('123456'),'张三丰','经理');
insert into employee values (null,'6668622',md5('123456'),'小龙女','服务员');
insert into employee values (null,'6668633',md5('123456'),'张无忌','收银员');
insert into employee values (null,'666',md5('123456'),'zzp','经理');

select * from employee;

domain层:

package com.zzpedu.mhl.domain;

/**
 * 这是一个javabean 和 employee对应
 */
public class Employee {
    private Integer id;
    private String empId;
    private String pwd;
    private String name;
    private String job;

    public Employee() {//无参构造器,底层apache-dbutils反射需要
    }

    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getEmpId() { return empId; }
    public void setEmpId(String empId) { this.empId = empId; }
    public String getPwd() { return pwd; }
    public void setPwd(String pwd) { this.pwd = pwd; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getJob() { return job; }
    public void setJob(String job) { this.job = job; }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", empId='" + empId + '\'' +
                ", pwd='" + pwd + '\'' +
                ", name='" + name + '\'' +
                ", job='" + job + '\'' +
                '}';
    }
}

dao层

package com.zzpedu.mhl.dao;

import com.zzpedu.mhl.domain.Employee;

/**
 * EmployeeDAO
 */
public class EmployeeDAO extends BasicDAO<Employee> {
    //这里还可以特有的操作
}

service层:

package com.zzpedu.mhl.service;

import com.zzpedu.mhl.dao.EmployeeDAO;
import com.zzpedu.mhl.domain.Employee;

/**
 * 该类完成对employee表的各种操作(通过调用EmployeeDAO对象完成)
 */
public class EmployeeService {

    //定义一个 EmployeeDAO属性
    private EmployeeDAO employeeDAO = new EmployeeDAO();

    //方法,根据empId 和 pwd 返回一个Employee对象
    //如果查询不到,返回null
    public Employee getEmployeeByIdAndPwd(String id,String pwd){
        return employeeDAO.querySingle("select * from employee where empId=? and pwd=md5(?)",
                Employee.class, id, pwd);
    }
}

view层:

修改MHLView类,添加用户登录判断

/**
 * 这是主界面
 */
public class MHLView {


    //定义一个 EmployeeService属性
    private EmployeeService employeeService = new EmployeeService();

    public static void main(String[] args) {
        new MHLView().mainMenu();
    }

    //显示主菜单方法
    public void mainMenu(){
        while (loop){
          ....
            switch (key){
                case "1":
                    System.out.print("输入员工号: ");
                    String empId = Utility.readString(50);
                    System.out.print("输入密  码: ");
                    String pwd = Utility.readString(50);
                    //到数据库去判断
                    Employee employee = employeeService.getEmployeeByIdAndPwd(empId, pwd);
                    if(employee != null){
                        System.out.println("==============登录成功[" + employee.getName() + "]==============\n");
                        //显示二级菜单,这里二级菜单是循环操作,所以做成while
                        while (loop){
                          ......
    }
}



显示餐桌状态

在这里插入图片描述

创建餐桌表

-- 创建 diningTable 餐桌表(id,state,orderName,orderTel)
create table diningTable(
		id int primary key auto_increment, # 自增,表示餐桌编号
		state varchar(20) not null default '', # 餐桌的状态
		orderName varchar(50) not null default '', # 预定人的名字
		orderTel varchar(20) not null default '' # 预定人的手机号
) charset=utf8;
# 测试数据
insert into diningTable values (null,'空','','');
insert into diningTable values (null,'空','','');
insert into diningTable values (null,'空','','');

select * from diningTable;

domain层

package com.zzpedu.mhl.domain;

/**
 * 这是一个javabean 和 diningTable表对应
 */
public class DiningTable {
    private Integer id;
    private String state;
    private String orderName;
    private String orderTel;

    public DiningTable() {
    }

    public DiningTable(Integer id, String state, String orderName, String orderTel) {
        this.id = id;
        this.state = state;
        this.orderName = orderName;
        this.orderTel = orderTel;
    }

    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getState() { return state; }
    public void setState(String state) { this.state = state; }
    public String getOrderName() { return orderName; }
    public void setOrderName(String orderName) { this.orderName = orderName; }
    public String getOrderTel() { return orderTel; }
    public void setOrderTel(String orderTel) { this.orderTel = orderTel; }

    @Override
    public String toString() {
       return id + "\t\t\t" + state;
    }
}

dao层

package com.zzpedu.mhl.dao;

import com.zzpedu.mhl.domain.DiningTable;

/**
 * DiningTableDAO
 */
public class DiningTableDAO extends BasicDAO<DiningTable>{
    //这里还可以特有的操作,可以写在 DiningTableDAO
}

service层

package com.zzpedu.mhl.service;

import com.zzpedu.mhl.dao.DiningTableDAO;
import com.zzpedu.mhl.domain.DiningTable;

import java.util.List;

/**
 * 该类完成对diningTable表的各种操作(通过调用DiningTableDAO对象完成)
 */
public class DiningTableService {//业务层
    //定义一个 DiningTableDAO 对象
    private DiningTableDAO diningTableDAO = new DiningTableDAO();

    //返回所有餐桌的信息
    public List<DiningTable> list(){
        return diningTableDAO.queryMulti("select id,state from diningTable",DiningTable.class);
    }
}

view层:

修改MHLView类,添加显示所有餐桌状态功能

package com.zzpedu.mhl.view;

import com.zzpedu.mhl.domain.DiningTable;
import com.zzpedu.mhl.domain.Employee;
import com.zzpedu.mhl.service.DiningTableService;
import com.zzpedu.mhl.service.EmployeeService;
import com.zzpedu.mhl.utils.Utility;

import java.util.List;

/**
 * 这是主界面
 */
public class MHLView {

	...
    //定义一个 DiningTableService属性
    private DiningTableService diningTableService = new DiningTableService();


    //显示所有餐桌状态
    public void listDiningTable(){
        List<DiningTable> list = diningTableService.list();
        System.out.println("\n餐桌编号\t\t餐桌状态");
        for(DiningTable diningTable : list){
            System.out.println(diningTable);
        }
        System.out.println("\n==============显示完毕==============");
    }


    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
       ...
            key = Utility.readString(1);
            switch (key){
                case "1":
                    System.out.print("输入员工号: ");
                    String empId = Utility.readString(50);
                    System.out.print("输入密  码: ");
                    String pwd = Utility.readString(50);
                    //到数据库去判断
                    Employee employee = employeeService.getEmployeeByIdAndPwd(empId, pwd);
                    if(employee != null){
                        System.out.println("==============登录成功[" + employee.getName() + "]==============\n");
                        //显示二级菜单,这里二级菜单是循环操作,所以做成while
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单==============");
                   ....
                            switch (key){
                                case "1":
                                    listDiningTable();//显示餐桌状态
                                    break;
        						.....
}

执行效果:

在这里插入图片描述


订座

功能说明:如果该订餐桌处于已经预定或者就餐状态,给出提示

在这里插入图片描述

分析:(1)要检查餐桌是否存在 (2)要检查餐桌的状态

在DiningTableService类,添加查询,更新方法

/**
 * 该类完成对diningTable表的各种操作(通过调用DiningTableDAO对象完成)
 */
public class DiningTableService {//业务层
    //定义一个 DiningTableDAO 对象
    private DiningTableDAO diningTableDAO = new DiningTableDAO();

 	....

    //根据id查询对应餐桌 DiningTable对象
    //如果返回null,表示id编号对应的餐桌不存在
    public DiningTable getDiningTableById(int id){
        return diningTableDAO.querySingle("select * from diningTable where id=?",DiningTable.class,id);
    }

    //如果餐桌可以预定,调用方法,对其状态进行更新(包括预订人和手机号)
    public boolean orderDiningTable(int id,String orderName,String orderTel){
        int update =
                diningTableDAO.update("update diningTable set state='已经预定',orderName=?,orderTel=? where id=?", orderName, orderTel, id);
        return update > 0;
    }

}

view层:

修改MHLView类,添加完成订座方法

/**
 * 这是主界面
 */
public class MHLView {

  	...
  	 //定义一个 DiningTableService属性
    private DiningTableService diningTableService = new DiningTableService();
    
    //完成订座
    public void orderDiningTable(){
        System.out.println("==============预定餐桌==============");
        System.out.print("请选择要预定的餐桌编号(-1 退出): ");
        int orderId = Utility.readInt();
        if(orderId == -1){
            System.out.println("==============取消预定餐桌==============");
            return;
        }
        //该方法得到的是 Y 或者 N
        char key = Utility.readConfirmSelection();
        if(key == 'Y'){//要预定
            //根据 orderId 返回对应的 DiningTable对象,如果为null,说明该对象不存在
            DiningTable diningTableById = diningTableService.getDiningTableById(orderId);
            if(diningTableById == null){
                System.out.println("==============预定餐桌不存在==============");
                return;
            }
            //判断该餐桌状态是否 “空”
            if(!"空".equals(diningTableById.getState())){//说明当前餐桌不是 “空” 状态
                System.out.println("==============该餐桌已经预定或者就餐中==============");
                return;
            }
            //这时说明可以真的预占
            System.out.print("预定人的名字: ");
            String orderName = Utility.readString(50);
            System.out.print("预定人的电话: ");
            String orderTel = Utility.readString(50);

            //更新餐桌状态
            if(diningTableService.orderDiningTable(orderId, orderName, orderTel)){
                System.out.println("==============预定餐桌成功==============");
            }else {
                System.out.println("==============预定餐桌失败==============");
            }
        }else {
            System.out.println("==============取消预定餐桌==============");
        }
    }

    
    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
         ...
            switch (key){
                case "1":
                   ....
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单==============");
                        .....
                            switch (key){
                                case "1":
                                    listDiningTable();//显示餐桌状态
                                    break;
                                case "2":
                                    orderDiningTable();
                                    break;
                              ......

    }
}

执行效果:
在这里插入图片描述


显示菜品

在这里插入图片描述

创建菜谱表

-- 创建 meun(菜谱)表(id,name,trpe,price)
create table menu(
		id int primary key auto_increment, # 自增主键,作为菜谱编号(唯一)
		`name` varchar(50) not null default '', # 菜谱名称
		type varchar(12) not null default '', # 菜谱种类
		price double not null default 0 # 价格
)charset=utf8;
# 测试数据
insert into menu values (null,'八宝饭','主食',10);
insert into menu values (null,'叉烧包','主食',20);
insert into menu values (null,'宫保鸡丁','热菜',30);
insert into menu values (null,'山药拨鱼','凉菜',14);
insert into menu values (null,'银丝卷','甜食',9);
insert into menu values (null,'水煮鱼','热菜',26);
insert into menu values (null,'甲鱼汤','汤类',100);
insert into menu values (null,'鸡蛋汤','汤类',16);

select * from menu;

domain层

package com.zzpedu.mhl.domain;

/**
 * 这是一个javabean 和 menu表对应
 */
public class Menu {
    private Integer id;
    private String name;
    private String type;
    private Double price;

    public Menu() {//无参构造器
    }

    public Menu(Integer id, String name, String type, Double price) {
        this.id = id;
        this.name = name;
        this.type = type;
        this.price = price;
    }

    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getType() { return type; }
    public void setType(String type) { this.type = type; }
    public Double getPrice() { return price; }
    public void setPrice(Double price) { this.price = price; }

    @Override
    public String toString() {
        return id + "\t\t\t" + name + "\t\t" + type + "\t\t" + price;
    }
}

dao层

package com.zzpedu.mhl.dao;

import com.zzpedu.mhl.domain.Menu;

/**
 * MenuDAO
 */
public class MenuDAO extends BasicDAO<Menu>{
}

service层

package com.zzpedu.mhl.service;

import com.zzpedu.mhl.dao.MenuDAO;
import com.zzpedu.mhl.domain.Menu;

import java.util.List;

/**
 * 该类完成对menu表的各种操作(通过调用MenuDAO对象完成)
 */
public class MenuService {

    //定义 MenuDAO属性
    private MenuDAO menuDao = new MenuDAO();

    //返回使用的菜品,返回给界面使用
    public List<Menu> list(){
        return menuDao.queryMulti("select * from menu",Menu.class);
    }
}

view层:

修改MHLView类,添加 显示所有菜品方法

package com.zzpedu.mhl.view;

import com.zzpedu.mhl.domain.DiningTable;
import com.zzpedu.mhl.domain.Employee;
import com.zzpedu.mhl.domain.Menu;
import com.zzpedu.mhl.service.DiningTableService;
import com.zzpedu.mhl.service.EmployeeService;
import com.zzpedu.mhl.service.MenuService;
import com.zzpedu.mhl.utils.Utility;

import java.util.List;

/**
 * 这是主界面
 */
public class MHLView {

    //定义一个 MenuService属性
    private MenuService menuService = new MenuService();

	....

    //显示所有菜品
    public void listMenu(){
        System.out.println("\n菜品编号\t\t菜品名\t\t类别\t\t价格");
        List<Menu> list = menuService.list();
        for(Menu menu : list){
            System.out.println(menu);
        }
        System.out.println("==============显示完毕==============");
    }


    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
            ....
            key = Utility.readString(1);
            switch (key){
                case "1":
				....
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单=============="); 
                            switch (key){
                                case "1":
                                    listDiningTable();//显示餐桌状态
                                    break;
                                case "2":
                                    orderDiningTable();
                                    break;
                                case "3":
                                    listMenu();
                                    break;
      ....
}

执行效果:

在这里插入图片描述


点餐

在这里插入图片描述

功能说明:要求对 餐桌号,菜品编号,做出合理性效验,如果不合理,给出提示信息

思路分析:(1) 餐桌号,菜品编号 效验 (2)点餐成功,需要修改餐桌状态 (3)生成账单

创建bill账单表

-- 增加表 bill 账单表(id,billId,menu,nums,billDate,money,state,diningTableId)
# 账单流水,考虑可以分开结账,并考虑将来分别统计各个不同菜品的销售情况
create table bill(
		id int primary key auto_increment, # 自增主键
		billId varchar(50) not null default '', # 账单号可以按自己的规则生成 uuid
		menuId int not null default 0, # 菜品的编号,也可以使用外键
		nums int not null default 0, # 份数
		money double not null default 0, # 金额
		diningTableId int not null default 0, # 餐桌
		billDate datetime not null, # 订单日期
		state varchar(24) not null default '' # 状态 '未结账' '已经结账' '挂单' '现金' '支付宝' '坏账'
)charset=utf8;

select * from bill;

domain层

package com.zzpedu.mhl.domain;

import java.util.Date;

/**
 * 这是一个javabean 和 bill表对应
 */
public class Bill {
    private Integer id;
    private String billId;
    private Integer menuId;
    private Integer nums;
    private Double money;
    private Integer diningTableId;
    private Date billDate;
    private String state;

    public Bill() {
    }

    public Bill(Integer id, String billId, Integer menuId, Integer nums, Double money, Integer diningTableId, Date billDate, String state) {
        this.id = id;
        this.billId = billId;
        this.menuId = menuId;
        this.nums = nums;
        this.money = money;
        this.diningTableId = diningTableId;
        this.billDate = billDate;
        this.state = state;
    }

    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getBillId() { return billId; }
    public void setBillId(String billId) { this.billId = billId; }
    public Integer getMenuId() { return menuId; }
    public void setMenuId(Integer menuId) { this.menuId = menuId; }
    public Integer getNums() { return nums; }
    public void setNums(Integer nums) { this.nums = nums; }
    public Double getMoney() { return money; }
    public void setMoney(Double money) { this.money = money; }
    public Integer getDiningTableId() { return diningTableId; }
    public void setDiningTableId(Integer diningTableId) { this.diningTableId = diningTableId; }
    public Date getBillDate() { return billDate; }
    public void setBillDate(Date billDate) { this.billDate = billDate; }
    public String getState() { return state; }
    public void setState(String state) { this.state = state; }
}

dao层

package com.zzpedu.mhl.dao;

import com.zzpedu.mhl.domain.Bill;

/**
 * BillDAO
 */
public class BillDAO extends BasicDAO<Bill>{
}

service层

package com.zzpedu.mhl.service;

import com.zzpedu.mhl.dao.BillDAO;

import java.util.UUID;

/**
 * 该类完成对bill表的各种操作(通过调用BillDAO对象完成) 处理和账单相关的业务逻辑
 */
public class BillService {
    //定义一个 BillDAO 对象
    private BillDAO billDAO = new BillDAO();
    //定义 MenuService属性
    private MenuService menuService = new MenuService();
    //定义 DiningTableService属性
    private DiningTableService diningTableService = new DiningTableService();

    //思考:
    //编写点餐的方法
    //1. 生成账单
    //2. 对应餐桌的状态
    //3. 如果成功返回true,否则返回false
    public boolean orderMenu(int menuId,int nums,int diningTaleId){
        //生成一个账单号,UUID
        String billId = UUID.randomUUID().toString();

        //将账单生成到bill表,要求直接计算账单金额
        int update = billDAO.update("insert into bill values (null,?,?,?,?,?,now(),'未结账')",
                billId, menuId, nums, menuService.getMenuById(menuId).getPrice() * nums, diningTaleId);
        if(update <= 0){
            return false;
        }
        //需要更新对应的餐桌状态
        return diningTableService.updateDiningTableState(diningTaleId,"就餐中");
    }
}

MenuService类,添加查询方法

/**
 * 该类完成对menu表的各种操作(通过调用MenuDAO对象完成)
 */
public class MenuService {
    //定义 MenuDAO属性
    private MenuDAO menuDao = new MenuDAO();
	....

    //需要方法,根据id,返回Menu对象
    public Menu getMenuById(int id){
        return menuDao.querySingle("select * from menu where id=?",Menu.class,id);
    }
}

DiningTableService类,添加更新方法

/**
 * 该类完成对diningTable表的各种操作(通过调用DiningTableDAO对象完成)
 */
public class DiningTableService {//业务层
    //定义一个 DiningTableDAO 对象
    private DiningTableDAO diningTableDAO = new DiningTableDAO();

   	....
    //需要提供一个更新 餐桌状态的方法
    public boolean updateDiningTableState(int id,String state){
        int update =
                diningTableDAO.update("update diningTable set state=? where id=?", state,id);
        return update > 0;
    }

}

view层:

修改MHLView类,添加点餐方法

/**
 * 这是主界面
 */
public class MHLView {

   	....
    //定义一个 BillService属性
    private BillService billService = new BillService();

    //完成订餐
    public void orderMenu(){
        System.out.println("==============点餐服务==============");
        System.out.print("请输入点餐的桌号(-1退出): ");
        int orderDiningTableId = Utility.readInt();
        if(orderDiningTableId == -1){
            System.out.println("==============取消点餐==============");
            return;
        }
        System.out.print("请输入点餐的菜品号(-1退出): ");
        int orderMenuId = Utility.readInt();
        if(orderMenuId == -1){
            System.out.println("==============取消点餐==============");
            return;
        }
        System.out.print("请输入点餐的菜品量(-1退出): ");
        int orderNums = Utility.readInt();
        if(orderNums == -1){
            System.out.println("==============取消点餐==============");
            return;
        }
        //验证餐桌号是否存在
        DiningTable diningTableById = diningTableService.getDiningTableById(orderDiningTableId);
        if(diningTableById == null){
            System.out.println("==============餐桌号不存在==============");
            return;
        }
        //验证菜品编号
        Menu menuById = menuService.getMenuById(orderMenuId);
        if(menuById == null){
            System.out.println("==============菜品号不存在==============");
            return;
        }
        //点餐
       if(billService.orderMenu(orderMenuId, orderNums, orderDiningTableId)){
           System.out.println("==============点餐成功==============");
       }else {
           System.out.println("==============点餐失败==============");
       }
    }

    ....

    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
           ...
            switch (key){
                case "1":
                    System.out.print("输入员工号: ");
                   ...
                    if(employee != null){
                        System.out.println("==============登录成功[" + employee.getName() + "]==============\n");
                        //显示二级菜单,这里二级菜单是循环操作,所以做成while
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单==============");
                          ...
                            switch (key){
                                case "1":
                                    listDiningTable();//显示餐桌状态
                                    break;
                                case "2":
                                    orderDiningTable();
                                    break;
                                case "3":
                                    listMenu();
                                    break;
                                case "4":
                                    orderMenu();
                                    break;
                                ....

    }
}

执行效果:

在这里插入图片描述


查看账单

在这里插入图片描述

domian层
Bill类,重写toString()方法

/**
 * 这是一个javabean 和 bill表对应
 */
public class Bill {
	....
    @Override
    public String toString() {
        return id + "\t\t" + menuId + "\t\t\t" + nums + "\t\t\t" +
                money + "\t" + diningTableId + "\t\t" + billDate + "\t\t" + state;
    }
}

service层
BillService类,添加查询所有账单方法

/**
 * 该类完成对bill表的各种操作(通过调用BillDAO对象完成) 处理和账单相关的业务逻辑
 */
public class BillService {
    //定义一个 BillDAO 对象
    private BillDAO billDAO = new BillDAO();
    .....
    //返回所有的账单,提供View调用
    public List<Bill> list(){
        return billDAO.queryMulti("select * from bill",Bill.class);
    }
}

view层

修改MHLView类,添加显示所有账单方法

/**
 * 这是主界面
 */
public class MHLView {

    ...
    //定义一个 BillService属性
    private BillService billService = new BillService();

 
    //显示账单信息
    public void listBill(){
        System.out.println("\n编号\t\t菜品号\t\t菜品量\t\t金额\t\t桌号\t\t日期\t\t\t\t\t\t\t状态");
        List<Bill> allBills = billService.list();
        for (Bill bill : allBills) {
            System.out.println(bill);
        }
        System.out.println("==============显示完毕==============");
    }


    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
         ...
            switch (key){
                case "1":
                    ...
                    if(employee != null){
                        System.out.println("==============登录成功[" + employee.getName() + "]==============\n");
                        //显示二级菜单,这里二级菜单是循环操作,所以做成while
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单==============");
                         ...
                            switch (key){
                               ...
                                case "5":
                                    listBill();//显示所有账单
                                    break;
                              ....
    }
}

结账

在这里插入图片描述

思路分析:(1)对餐桌号进行效验 (2)修改bill表状态state (3)修改diningTable信息 (4)不需要增加新表,不需要增加新的类,需要增加方法

service层:

在BillService类,添加两个方法

/**
 * 该类完成对bill表的各种操作(通过调用BillDAO对象完成) 处理和账单相关的业务逻辑
 */
public class BillService {
    //定义一个 BillDAO 对象
    private BillDAO billDAO = new BillDAO();
    //定义 DiningTableService属性
    private DiningTableService diningTableService = new DiningTableService();

   ...
    //查看某个餐桌是否有未结账的账单
    public boolean hasPayBillByDiningTableId(int diningTableId){
        Bill bill =
                billDAO.querySingle("select * from bill where diningTableId=? and state='未结账' limit 0, 1",
                                    Bill.class, diningTableId);
        return bill != null;
    }

    //完成结账[如果餐桌存在,并且该餐桌有未结账的账单]
    //如果成功,返回true,失败返回false
    public boolean payBill(int diningTableId,String payMode){
    	 //如果这里使用事务的话,需要用ThreadLocal来解决,框架中比如:mybatis 提供了事务支持
        //1. 修改bill表
        int update =
                billDAO.update("update bill set state=? where diningTableId=? and state='未结账'", payMode,diningTableId);
        if(update <= 0){//如果更新没有成功,则表示失败
            return false;
        }
        //2. 修改diningTable表
        //注意,不要直接在这里操作,而应该调用DiningTableService 方法,完成更新,体现各司其职
        if(diningTableService.updateDiningTableToFree(diningTableId,"空")){
            return true;
        }
        return false;
    }
}

在DiningTableService类,添加方法

/**
 * 该类完成对diningTable表的各种操作(通过调用DiningTableDAO对象完成)
 */
public class DiningTableService {//业务层
    //定义一个 DiningTableDAO 对象
    private DiningTableDAO diningTableDAO = new DiningTableDAO();

    ...

    //提供方法,将指定的餐桌设置为空闲状态
    public boolean updateDiningTableToFree(int id,String state){
        int update =
                diningTableDAO.update("update diningTable set state=?,orderName='',orderTel='' where id=?", state,id);
        return update > 0;
    }

}

view层:

修改MHLView类,添加结账方法:

package com.zzpedu.mhl.view;

import com.zzpedu.mhl.domain.Bill;
import com.zzpedu.mhl.domain.DiningTable;
import com.zzpedu.mhl.domain.Employee;
import com.zzpedu.mhl.domain.Menu;
import com.zzpedu.mhl.service.BillService;
import com.zzpedu.mhl.service.DiningTableService;
import com.zzpedu.mhl.service.EmployeeService;
import com.zzpedu.mhl.service.MenuService;
import com.zzpedu.mhl.utils.Utility;

import java.util.List;

/**
 * 这是主界面
 */
public class MHLView {

 	...
    //定义一个 DiningTableService属性
    private DiningTableService diningTableService = new DiningTableService();
    //定义一个 BillService属性
    private BillService billService = new BillService();


    //完成结账
    public void payBill(){
        System.out.println("==============结账服务==============");
        System.out.print("请选择要结账的餐桌编号(-1退出): ");
        int diningTableId = Utility.readInt();
        if(diningTableId == -1){
            System.out.println("==============取消结账==============");
            return;
        }
        //验证餐桌号是否存在
        DiningTable diningTableById = diningTableService.getDiningTableById(diningTableId);
        if(diningTableById == null){
            System.out.println("==============结账的餐桌号不存在==============");
            return;
        }
        //验证餐桌是否需要结账的账单
        if(!billService.hasPayBillByDiningTableId(diningTableId)){
            System.out.println("==============该餐位没有未结账账单==============");
            return;
        }
        System.out.print("结账方式(现金/支付宝/微信)回车表示退出: ");
        String payMode = Utility.readString(20,"");//说明如果是回车,就是返回 ""
        if("".equals(payMode)){
            System.out.println("==============取消结账==============");
            return;
        }
        char key = Utility.readConfirmSelection();
        if(key == 'Y'){//结账
            //调用方法
            if(billService.payBill(diningTableId,payMode)){
                System.out.println("==============完成结账==============");
            }else {
                System.out.println("==============结账失败==============");
            }
        }else {
            System.out.println("==============取消结账==============");
        }
    }


    ...

    //显示主菜单方法
    public void mainMenu(){
        while (loop){
            System.out.println("==============满汉楼==============");
         ...
            switch (key){
                case "1":
                   ...
                    if(employee != null){
                        System.out.println("==============登录成功[" + employee.getName() + "]==============\n");
                        //显示二级菜单,这里二级菜单是循环操作,所以做成while
                        while (loop){
                            System.out.println("\n==============满汉楼二级菜单==============");
                            ...
                            switch (key){
                                ..
                                case "6":
                                    payBill();
                                    break;
                               ....
    }
}

执行效果:

在这里插入图片描述


满汉楼 - 扩展思考

思考1:如果 多表查询 怎么处理?比如:查看账单时,希望显示菜品名称,怎么办? =>> 给出思路:https://www.pianshen.com/article/48341042440/

在这里插入图片描述

domain层

package com.zzpedu.mhl.domain;

import java.util.Date;

/**
 * 这是一个javabean,可以多张表进行对应
 */
public class MultiTableBean {
    //bill表字段
    private Integer id;
    private String billId;
    private Integer menuId;
    private Integer nums;
    private Double money;
    private Integer diningTableId;
    private Date billDate;
    private String state;
    //增加一个来自menu表的列
    //思考 这里的属性名是否一定要和表列名保持一致
    // 解决:可以不一致,可以sql语句使用别名
    private String name2;
    private Double price;//默认值为null

    public MultiTableBean() {
        System.out.println("反射调用的....");
    }

	//getter setter方法...

    @Override
    public String toString() {
        return id + "\t\t" + menuId + "\t\t\t" + nums + "\t\t\t" +
                money + "\t" + diningTableId + "\t\t" + billDate + "\t\t" +
                state + "\t\t" + name2 + "\t\t" + price;
    }
}

dao层

package com.zzpedu.mhl.dao;

import com.zzpedu.mhl.domain.MultiTableBean;

/**
 * MultiTableDAO
 */
public class MultiTableDAO extends BasicDAO<MultiTableBean>{
}

service层
在BillService添加查询方法

package com.zzpedu.mhl.service;

import com.zzpedu.mhl.dao.BillDAO;
import com.zzpedu.mhl.dao.MultiTableDAO;
import com.zzpedu.mhl.domain.Bill;
import com.zzpedu.mhl.domain.MultiTableBean;

import java.util.List;
import java.util.UUID;

/**
 * 该类完成对bill表的各种操作(通过调用BillDAO对象完成) 处理和账单相关的业务逻辑
 */
public class BillService {
 
	
    //定义 MultiTableDAO属性
    private MultiTableDAO multiTableDAO = new MultiTableDAO();
	...
    //返回所有的账单并带有菜品名称,提供View调用
    public List<MultiTableBean> list2(){
        return multiTableDAO.queryMulti("select bill.*, name as name2,price from bill,menu where bill.menuId = menu.id",MultiTableBean.class);
    }
}

view层

修改MHLView类的listBill方法

/**
 * 这是主界面
 */
public class MHLView {
	....
	//显示账单信息
    public void listBill(){
//        System.out.println("\n编号\t\t菜品号\t\t菜品量\t\t金额\t\t桌号\t\t日期\t\t\t\t\t\t\t状态");
//        List<Bill> allBills = billService.list();
//        for (Bill bill : allBills) {
//            System.out.println(bill);
//        }
//        System.out.println("==============显示完毕==============");
        System.out.println("\n编号\t\t菜品号\t\t菜品量\t\t金额\t\t桌号\t\t日期\t\t\t\t\t\t\t状态\t\t菜品名\t\t价格");
        List<MultiTableBean> allBills = billService.list2();
        for (MultiTableBean bill : allBills) {
            System.out.println(bill);
        }
        System.out.println("==============显示完毕==============");
    }
}

执行效果:
在这里插入图片描述


思考2:员工信息字段可能有很多,而且员工数也会很多,为提高效率,可以采用 分表设计 employee 和 login

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值