Java综合项目 - 房屋出租系统(crud增删改查以及信息列表)

系统需求

  1. 总需求
    在这里插入图片描述
  2. 系统界面展示

2.1 主菜单
2.2 新增房源
2.3 查找房源
2.4 删除房源
2.5 修改房源
2.6 房屋列表
2.7 退出系统

2.1 主菜单
在这里插入图片描述
2.2 新增房源
在这里插入图片描述
2.3 查找房源
在这里插入图片描述
2.4 删除房源
在这里插入图片描述
2.5 修改房源
在这里插入图片描述
2.6 房屋列表
在这里插入图片描述
2.7 退出系统
在这里插入图片描述

项目设计

在这里插入图片描述
分层模式(界面层,业务层,model层):
在这里插入图片描述

一、工具类

  1. 工具类介绍
    在这里插入图片描述

  2. 注意:静态方法可以直接通过类名调用
    在这里插入图片描述

  3. 工具类代码

package com.wpangzi.houserent.utils;

/**
 工具类的作用:
 处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
 */

import java.util.*;

public class Utility {
    //静态属性。。。
    private static Scanner scanner = new Scanner(System.in);

    /**
     * 功能:读取键盘输入的一个菜单选项,值:1——5的范围
     * @return 1——5
     */
    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') {
                System.out.print("选择错误,请重新输入:");
            } 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;
        for (; ; ) {
            String str = readKeyBoard(10, false);//一个整数,长度<=10位
            try {
                n = Integer.parseInt(str);//将字符串转换成整数
                break;
            } catch (NumberFormatException e) {
                System.out.print("数字输入错误,请重新输入:");
            }
        }
        return n;
    }
    /**
     * 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
     * @param defaultValue 指定的默认值
     * @return 整数或默认值
     */
    public static int readInt(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.print("数字输入错误,请重新输入:");
            }
        }
        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.println("请输入你的选择(Y/N): 请小心选择");
        char c;
        for (; ; ) {//无限循环
            //在这里,将接受到字符,转成了大写字母
            //y => Y n=>N
            String str = readKeyBoard(1, false).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("选择错误,请重新输入:");
            }
        }
        return c;
    }

    /**
     * 功能: 读取一个字符串
     * @param limit 读取的长度
     * @param blankReturn 如果为true ,表示 可以读空字符串。
     * 					  如果为false表示 不能读空字符串。
     *
     *	如果输入为空,或者输入大于limit的长度,就会提示重新输入。
     * @return
     */
    private static String readKeyBoard(int limit, boolean blankReturn) {

        //定义了字符串
        String line = "";

        //scanner.hasNextLine() 判断有没有下一行
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();//读取这一行

            //如果line.length=0, 即用户没有输入任何内容,直接回车
            if (line.length() == 0) {
                if (blankReturn) return line;//如果blankReturn=true,可以返回空串
                else continue; //如果blankReturn=false,不接受空串,必须输入内容
            }

            //如果用户输入的内容大于了 limit,就提示重写输入
            //如果用户如的内容 >0 <= limit ,我就接受
            if (line.length() < 1 || line.length() > limit) {
                System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
                continue;
            }
            break;
        }

        return line;
    }
}


二、编写House类

  1. 找属性
    根据房屋列表可知基本属性有这6个
    在这里插入图片描述
  2. 代码
  • 私有属性
  • 构造器
  • get和set方法
  • 重写toString方法(按照自己需要的输出)
package com.wpangzi.houserent.domain;

/**
 * House的对象表示一个基本信息
 */
public class House {
    //编号,房主,电话,地址,月租,状态(已出租/未出租)
    private int id;
    private String name;
    private String phone;
    private String address;
    private int rent;
    private String state;
    //构造器和get。set方法
    public House(int id, String name, String phone, String address, int rent, String state) {
        this.id = id;
        this.name = name;
        this.phone = phone;
        this.address = address;
        this.rent = rent;
        this.state = state;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getRent() {
        return rent;
    }

    public void setRent(int rent) {
        this.rent = rent;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    //按照房屋列表重写toString方法

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

三、实现主菜单

  1. 总要求
    在这里插入图片描述
  2. 实现分析
    在这里插入图片描述
  3. 代码编写
package com.wpangzi.houserent.view;

import com.wpangzi.houserent.utils.Utility;

import java.util.Scanner;

/**
 * 步骤是:
 * 1. 显示界面(输出界面提示内容)
 * 2. 接受用户输入(key)
 * 3. 调用HouseService完成对房屋信息的各种操作(用switch-case)
 */

public class HouseView {
    //属性
    private char key = ' ';//接收用户选择
    private boolean loop = true;//控制显示菜单
    //显示主菜单
    public void mainMenu(){
        do {
            System.out.println("========房屋出租系统========");
            System.out.println("\t\t1 新 增 房 源");
            System.out.println("\t\t2 查 找 房 屋");
            System.out.println("\t\t3 删除房屋信息");
            System.out.println("\t\t4 修改房屋信息");
            System.out.println("\t\t5 房屋列表");
            System.out.println("\t\t6 退出");
            System.out.print("请选择(1-6):");
            key = Utility.readChar();
            //注意这个key是字符不是数字!!
            switch (key){
                case '1':
                    System.out.println("--------添加房屋--------");
                    System.out.println("--------添加完成--------");
                    break;
                case '2':
                    System.out.println("--------查找房屋--------");
                    break;
                case '3':
                    System.out.println("--------删除房屋--------");
                    System.out.println("--------删除完成--------");
                    break;
                case '4':
                    System.out.println("--------修改房屋--------");
                    System.out.println("--------修改完成--------");
                    break;
                case '5':
                    System.out.println("--------房屋列表--------");
                    System.out.println("--------房屋列表完成--------");
                    break;
                case '6':
                    loop = false;
                    break;
                //总是忘记写默认
                default:
                    System.out.println("输入错误");
                    break;
            }
        }while (loop);
        //如果退出while循环,说明退出了程序
        System.out.println("你退出了程序~~");
    }
}

package com.wpangzi.houserent;

import com.wpangzi.houserent.utils.Utility;
import com.wpangzi.houserent.view.HouseView;

public class HouseRentAPP {
    public static void main(String[] args) {
        //创建HouseView对象,并且显示主菜单,是整个程序的入口
        /*
            这样显得很罗嗦,可以使用匿名对象直接调用
            HouseView houseView = new HouseView();
            houseView.mainMenu();
         */
        new HouseView().mainMenu();
    }
}

四、实现房屋出租列表

  1. 功能描述
    在这里插入图片描述
  2. 实现分析
    ① 房屋列表中数据的显示的格式需要在view中写且需调用业务层中返回数据的方法
    ② 业务层中需要定义数组,再给一个返回数组的方法
    在这里插入图片描述
  3. 代码编写
    ① 界面层(此部分-非全部)
  1. 显示界面部分
  2. 接收业务层返回的数据并遍历
  3. 注意遍历时对于null数据的处理 - 没有嵌套而是把不要的部分直接break
  4. 在switch中调用列表
	//创建HouseService对象来调用list方法,初始化HouseService对象(数组长度为10)
    private HouseService houseService = new HouseService(10);
    //...中间部分重复
    case '5':
	    listHouse();
	     break;
	//编写listHouse(),显示房屋列表
    public void listHouse(){
        System.out.println("--------房屋列表--------");
        System.out.println("编号\t房主\t\t电话\t\t\t地址\t\t月租\t\t状态(已出租/未出租)");
        House[] houses = houseService.list();//接收返回的House数组
        //遍历数组
        for (int i = 0; i < houses.length; i++) {
            /*
                如果元素为空,则不用显示了
                这里没有判断houses[i] != null则输出,为了少嵌套,少耦合
             */
            if (houses[i] == null) {
                break;
            }
            System.out.println(houses[i].toString());
        }
        System.out.println("--------房屋列表完成--------");
    }

② 业务层

  1. 零钱通例子用到的是字符串拼接
    因为列表中属性显示的格式不是按照对象的属性来的,做了修改
  2. 房屋出租这个例子用的是数组
    因为列表中属性显示的格式就是按对象属性来的,直接用实体类中的toString方法输出即可
    toString方法重写 - 写成列表需要的格式
  3. 在构造器中,当创建HouseService对象时,指定数组的大小
  4. 返回数组,让view中接受数组并遍历、显示
package com.wpangzi.houserent.service;

import com.wpangzi.houserent.domain.House;

/**
 * HouseService[业务层]
 * //定义House[],保存House对象
 * 1. 响应HouseView的调用
 * 2. 完成对房屋信息的各种操作(crud)
 */
public class HouseService {
    //属性
    /*
        1. 零钱通例子用到的是字符串拼接
        因为列表中属性显示的格式不是按照对象的属性来的,做了修改
        2. 房屋出租这个例子用的是数组
        因为列表中属性显示的格式就是按对象属性来的,直接用实体类中的toString方法输出即可
        toString方法重写 - 写成列表需要的格式
     */
    private House[] houses;//保存House对象

    //方法
    /*
        构造器
        1. House[]数组只初始化没有在堆中创建(因为不知道数组的大小)
        2. 当创建HouseService对象时,指定数组的大小
     */
    public HouseService(int size) {
        houses = new House[size];
        //为了配合测试,所以先初始化一个对象
        houses[0] = new House(1, "王胖子", "15800001111",
                "中国×××", 2000, "未出租");
    }

    //list方法,返回houses数组
    public House[] list(){
        return houses;
    }
}
  1. 效果
    在这里插入图片描述

五、实现添加房屋

  1. 总要求
    在这里插入图片描述

  2. 实现分析
    在这里插入图片描述

  3. 代码编写

  1. 把新增的房屋添加到数组中然后houseNums加1
    houseNums表示数组中已经有几个元素,用于判断是否需要扩容和当元素下标
    第一种:
    houses[houseNums] = newHouse;
    houseNums++;
    第二种:
    houses[houseNums++] = newHouse;
  2. 实现id自增长机制,然后更新newHouse的id
    第一种:
    idCounter++;
    newHouse.setId(idCounter);
    第二种:(先加后赋值)
    newHouse.setId(++idCounter);
  3. 数组扩充:house去接收调用数组扩充方法后返回的新数组(不能在方法中新数组赋值给旧数组,在方法外还是按原数组的…)

service节选部分代码

private House[] houses;//保存House对象
private int houseNums = 1;//记录当前有多少个房屋信息
private int idCounter = 1;//id计数器,记录当前id到哪个值
//add方法,添加新对象,返回Boolean
public boolean add(House newHouse){
    //判断是否还可以继续添加(我们暂时不考虑数组扩容的问题)
//        if (houseNums == houses.length){//不能再添加
//            System.out.println("数组已满,不能再添加");
//            return false;
//        }
    //考虑数组扩容
    if (houseNums >= houses.length){//调用数组扩容方法,数组扩1
        houses = copyHouse(houses);
    }
    /*
        把新增的房屋添加到数组中,然后houseNums加1
        第一种:
            houses[houseNums] = newHouse;
            houseNums++;
        第二种:
            houses[houseNums++] = newHouse;
     */
    houses[houseNums++] = newHouse;
    /*
        实现id自增长机制,然后更新newHouse的id
        第一种:
             idCounter++;
             newHouse.setId(idCounter);
        第二种:(先加后赋值)
             newHouse.setId(++idCounter);

     */
    newHouse.setId(++idCounter);
    return true;
}
//实现数组扩容
public House[] copyHouse(House[] houses){
    House[] houses1 = new House[houses.length+1];
    for (int i = 0; i < houses.length; i++) {
        houses1[i] = houses[i];
    }
    return houses1;
}

view节选部分代码

case '1':
addHouse();
break;
//编写addHouse(),接受输入,创建House对象,调用add方法
public void addHouse(){
    System.out.println("--------------------------添加房屋--------------------------");
    System.out.printf("姓名:");
    String name = Utility.readString(10);
    System.out.printf("电话:");
    String phone = Utility.readString(11);
    System.out.printf("地址:");
    String address = Utility.readString(20);
    System.out.printf("月租:");
    int rent = Utility.readInt(6);
    System.out.printf("状态(未出租/已出租):");
    String state = Utility.readString(3);
    //创建一个新的House对象,注意id是系统分配的(自增长),这里先写成0
    House newHouse = new House(0,name,phone,address,rent,state);
    if (houseService.add(newHouse)){
        System.out.println("--------------------------添加完成--------------------------");
    }else{
        System.out.println("--------------------------添加失败--------------------------");
    }
}
  1. 效果
    在这里插入图片描述

六、实现房屋删除

  1. 总要求
    在这里插入图片描述
  2. 实现分析
    在这里插入图片描述
  3. 代码
    service截取部分代码
//del(),删除一个房屋信息
public boolean del(int delId){
    /*
        1. 应当先找到要删除的房屋信息对相应的下标
        2. 注意:下标和房屋编号不是一个东西(各司其职)
        3. houseNums是指现在有多少个房屋信息,比如有2个
        4. 而数组有多大,下标就有多少个,比如定义数组长度是10,则下标可以为10
     */
    int index = -1;//用于接收id对应数组的下标
    for (int i = 0; i < houseNums; i++) {//要删除的房屋(id),是数组下标未i的元素
        if (delId == houses[i].getId()){
            index = delId;
        }
    }
    if (index == -1){//说明delId不存在
        return false;
    }
    /*
       1. 如果找到,则从下标index开始,每个元素前移,最后一个元素置空
          (这里的最后一个是指当前存在信息的最后一个)
       2. 后一个元素覆盖前一个,最后一个下标不参与循环,因为再加1就是空值或者越界了
       3. 删除之后要把houseNums--!!!
       3.1 第一种
            houses[houseNums-1] = null;
            houseNums --;//少一个
       3.2 第二种(这种自加加,自减减用很多的,如果要用到自增自减的要想到这个)
            houses[--houseNums] = null;
     */
    for (int i = index; i < houseNums - 1; i++) {
        houses[i] = houses[i+1];
    }
    houses[--houseNums] = null;
    return true;
}

view截取部分代码

if (houseService.del(delId))方法返回布尔值,在view类中调用并判断真假,然后输出界面的内容(service类中只写了删除的逻辑然后返回布尔值,让view类去判断真假输出界面内容)

case '3':
	delHouse();
	break;
//编写delHouse(),接收输入的id,调用Service的del方法
public void delHouse(){
    System.out.println("--------------------------删除房屋--------------------------");
    System.out.print("请输入待删除房屋的编号(-1退出):");
    int delId = Utility.readInt();
    if (delId == -1){
        System.out.println("-------------------------放弃删除房屋-------------------------");
        return;
    }
    //注意该方法本身就有循环判断的逻辑,必须输入Y/N,且自己输出了提示语句
    char choice = Utility.readConfirmSelection();
    if (choice == 'Y'){
        if (houseService.del(delId)){
            System.out.println("--------------------------删除成功--------------------------");
        }else {
            System.out.println("-----------------------没有该编号,删除失败-----------------------");
        }
    }else {
        System.out.println("-------------------------放弃删除房屋-------------------------");
    }
}
  1. 输出效果
    在这里插入图片描述

七、实现退出系统

  1. 总要求
    在这里插入图片描述
  2. 代码
    view部分
 //完成退出确认
    public void exitHouse(){
        System.out.printf("确认退出吗(Y/N):");
        //choice会接收到一个Y/N
        char choice = Utility.readConfirmSelection();
        if (choice == 'Y'){
            loop = false;
        }else {
            System.out.println("--------------------------放弃退出--------------------------");
        }
    }
  1. 输出效果
    在这里插入图片描述

八、实现根据id查找(多看看)

  1. 总要求
    在这里插入图片描述

  2. 实现分析
    在这里插入图片描述

  3. 代码
    service部分代码

//findById(),返回House对象或者null
public House findById(int findId) {
    /*
        findId和已有数据的id进行匹配,若匹配上则输出信息
        一定注意是和数组元素的id比较而不是和数组元素的下标比较!!!
        如果找到就返回这个house对象,如果没找到则返回空
        (比我那个返回当前下标然后使用get方法获取house对象的方法好)
     */
    for (int i = 0; i < houseNums; i++) {
        if (findId == houses[i].getId()) {
          return houses[i];
        }
    }
   return null;
}

view部分代码

//根据id查找房屋信息
public void findHouse() {
    System.out.println("--------------------------查找房屋--------------------------");
    System.out.printf("请输入你要查找的id:");
    int findId = Utility.readInt();
    //调用方法
    /*
        这是我没听老师讲之前用的方法,不太好
        1. 我调用方法接收了id对应的下标,然后用get方法获取house数组对应下标的信息
        2. 输出对象会自动调用toString方法System.out.println(house);
        int result =houseService.findById(findId);
        if (result != -1) {
            System.out.println(houseService.getHouses()[result].toString());
        } else {
            System.out.println("-------------------------没有该房屋--------------------------");
        }
    */
    House house = houseService.findById(findId);
    if (house != null) {
        System.out.println(house);
    } else {
        System.out.println("------------------------该id不存在-------------------------");
    }
}

  1. 输出效果
    在这里插入图片描述

九、实现修改房屋

  1. 总要求
    在这里插入图片描述
  2. 实现分析
    在这里插入图片描述
  3. 代码
    service代码用的是findById的代码
    view中部分代码

输入可以为空,所以要加一个判断
判断输入接收内容是否为空,不为空则修改,否则什么都不做

//根据id修改房屋信息
public void updateHouse() {
    System.out.println("-------------------------修改房屋信息-------------------------");
    System.out.printf("请选择待修改房屋编号(-1退出):");
    int updateId = Utility.readInt();
    if (updateId == -1) {
        System.out.println("--------------------------放弃修改--------------------------");
        return;
    }
    /*
        调用方法,方法会根据id 返回对象或null
        当判断里面的代码很多时,要想到可以使用过关斩将的思想
            先写出不正确的然后return
            这样正确的内容就不会嵌套在条件语句中
        下面是没听老师讲之前写的,条件语句中内容过多,没有想到过关斩将的思想
            且我返回的是id 对应数组的下标
     */
//        int index = houseService.update(updateId);
//        if (index != -1) {
//            System.out.printf("姓名(" + houseService.getHouses()[index].getName() + "):");
//            String name = Utility.readString(5, "");
//            houseService.getHouses()[index].setName(name);
//            System.out.printf("电话(" + houseService.getHouses()[index].getPhone() + "):");
//            String phone = Utility.readString(11, "13588889999");
//            System.out.printf("地址(" + houseService.getHouses()[index].getAddress() + "):");
//            String address = Utility.readString(11, "中国***");
//            System.out.printf("租金(" + houseService.getHouses()[index].getRent() + "):");
//            int rent = Utility.readInt(1000);
//            System.out.printf("状态(" + houseService.getHouses()[index].getState() + "):");
//            String state = Utility.readString(3, "未出租");
//            System.out.println("--------------------------修改成功--------------------------");
//        } else {
//            System.out.println("-------------------------不存在该房屋-------------------------");
//        }
    House house = houseService.findById(updateId);
    if (house == null) {
        System.out.println("----------------------修改房屋信息的编号不存在----------------------");
        return;
    }
    System.out.printf("姓名(" + house.getName() + "):");
    String name = Utility.readString(5, "");
    if (!"".equals(name)) {//如果name非空,则修改
        house.setName(name);
    }
    System.out.printf("电话(" + house.getPhone() + "):");
    String phone = Utility.readString(11, "");
    if (!"".equals(phone)) {//如果name非空,则修改
        house.setPhone(phone);
    }
    System.out.printf("地址(" + house.getAddress() + "):");
    String address = Utility.readString(11, "");
    if (!"".equals(address)) {//如果name非空,则修改
        house.setAddress(address);
    }
    System.out.printf("租金(" + house.getRent() + "):");
    int rent = Utility.readInt(-1);
    if (rent != -1) {//如果name非空,则修改
        house.setRent(rent);
    }
    System.out.printf("状态(" + house.getState() + "):");
    String state = Utility.readString(3, "");
    if (!"".equals(state)) {//如果name非空,则修改
        house.setState(state);
    }
    System.out.println("--------------------------修改成功--------------------------");
}
  1. 输出效果
    在这里插入图片描述

整体代码

  1. HouseRentAPP.java
package com.wpangzi.houserent;

import com.wpangzi.houserent.utils.Utility;
import com.wpangzi.houserent.view.HouseView;

public class HouseRentAPP {
    public static void main(String[] args) {
        //创建HouseView对象,并且显示主菜单,是整个程序的入口
        /*
            这样显得很罗嗦,可以使用匿名对象直接调用
            HouseView houseView = new HouseView();
            houseView.mainMenu();
         */
        new HouseView().mainMenu();
    }
}

  1. HouseView.java
package com.wpangzi.houserent.view;

import com.wpangzi.houserent.domain.House;
import com.wpangzi.houserent.service.HouseService;
import com.wpangzi.houserent.utils.Utility;

import java.util.Scanner;

/**
 * 步骤是:
 * 1. 显示界面(输出界面提示内容)
 * 2. 接受用户输入(key)
 * 3. 调用HouseService完成对房屋信息的各种操作(用switch-case)
 */

public class HouseView {
    //属性
    private char key = ' ';//接收用户选择
    private boolean loop = true;//控制显示菜单
    //创建HouseService对象来调用list方法,初始化HouseService对象(数组长度为10)
    private HouseService houseService = new HouseService(2);

    //显示主菜单
    public void mainMenu() {
        do {
            System.out.println("========房屋出租系统========");
            System.out.println("\t\t1 新 增 房 源");
            System.out.println("\t\t2 查 找 房 屋");
            System.out.println("\t\t3 删除房屋信息");
            System.out.println("\t\t4 修改房屋信息");
            System.out.println("\t\t5 房屋列表");
            System.out.println("\t\t6 退出");
            System.out.print("请选择(1-6):");
            key = Utility.readChar();
            //注意这个key是字符不是数字!!
            switch (key) {
                case '1':
                    addHouse();
                    break;
                case '2':
                    findHouse();
                    break;
                case '3':
                    delHouse();
                    break;
                case '4':
                    updateHouse();
                    break;
                case '5':
                    listHouse();
                    break;
                case '6':
                    exitHouse();
                    break;
                //总是忘记写默认
                default:
                    System.out.println("输入错误");
                    break;
            }
        } while (loop);
        //如果退出while循环,说明退出了程序
        System.out.println("你退出了程序~~");
    }

    //编写listHouse(),显示房屋列表
    public void listHouse() {
        System.out.println("--------------------------房屋列表-------------------------");
        System.out.println("编号\t房主\t\t电话\t\t\t地址\t\t月租\t\t状态(已出租/未出租)");
        House[] houses = houseService.list();//接收返回的House数组
        //遍历数组
        for (int i = 0; i < houses.length; i++) {
            /*
                如果元素为空,则不用显示了
                这里没有判断houses[i] != null则输出,为了少嵌套,少耦合
             */
            if (houses[i] == null) {
                break;
            }
            System.out.println(houses[i].toString());
        }
        System.out.println("------------------------房屋列表完成------------------------");
    }

    //编写addHouse(),接受输入,创建House对象,调用add方法
    public void addHouse() {
        System.out.println("--------------------------添加房屋--------------------------");
        System.out.printf("姓名:");
        String name = Utility.readString(10);
        System.out.printf("电话:");
        String phone = Utility.readString(11);
        System.out.printf("地址:");
        String address = Utility.readString(20);
        System.out.printf("月租:");
        int rent = Utility.readInt(6);
        System.out.printf("状态(未出租/已出租):");
        String state = Utility.readString(3);
        //创建一个新的House对象,注意id是系统分配的(自增长),这里先写成0
        House newHouse = new House(0, name, phone, address, rent, state);
        if (houseService.add(newHouse)) {
            System.out.println("--------------------------添加完成--------------------------");
        } else {
            System.out.println("--------------------------添加失败--------------------------");
        }
    }

    //编写delHouse(),接收输入的id,调用Service的del方法
    public void delHouse() {
        System.out.println("--------------------------删除房屋--------------------------");
        System.out.print("请输入待删除房屋的编号(-1退出):");
        int delId = Utility.readInt();
        if (delId == -1) {
            System.out.println("-------------------------放弃删除房屋-------------------------");
            return;
        }
        //注意该方法本身就有循环判断的逻辑,必须输入Y/N
        System.out.print("请小心选择:请输入你的选择(Y/N): ");
        char choice = Utility.readConfirmSelection();
        if (choice == 'Y') {
            if (houseService.del(delId)) {
                System.out.println("--------------------------删除成功--------------------------");
            } else {
                System.out.println("-----------------------没有该编号,删除失败-----------------------");
            }
        } else {
            System.out.println("-------------------------放弃删除房屋-------------------------");
        }
    }

    //完成退出确认
    public void exitHouse() {
        System.out.printf("确认退出吗(Y/N):");
        //choice会接收到一个Y/N
        char choice = Utility.readConfirmSelection();
        if (choice == 'Y') {
            loop = false;
        } else {
            System.out.println("--------------------------放弃退出--------------------------");
        }
    }

    //根据id查找房屋信息
    public void findHouse() {
        System.out.println("--------------------------查找房屋--------------------------");
        System.out.printf("请输入你要查找的id:");
        int findId = Utility.readInt();
        //调用方法
        /*
            这是我没听老师讲之前用的方法,不太好
            1. 我调用方法接收了id对应的下标,然后用get方法获取house数组对应下标的信息
            2. 输出对象会自动调用toString方法System.out.println(house);
            int result =houseService.findById(findId);
            if (result != -1) {
                System.out.println(houseService.getHouses()[result].toString());
            } else {
                System.out.println("-------------------------没有该房屋--------------------------");
            }
        */
        House house = houseService.findById(findId);
        if (house != null) {
            System.out.println(house);
        } else {
            System.out.println("------------------------该id不存在-------------------------");
        }
    }

    //根据id修改房屋信息
    public void updateHouse() {
        System.out.println("-------------------------修改房屋信息-------------------------");
        System.out.printf("请选择待修改房屋编号(-1退出):");
        int updateId = Utility.readInt();
        if (updateId == -1) {
            System.out.println("--------------------------放弃修改--------------------------");
            return;
        }
        /*
            调用方法,方法会根据id 返回对象或null
            当判断里面的代码很多时,要想到可以使用过关斩将的思想
                先写出不正确的然后return
                这样正确的内容就不会嵌套在条件语句中
            下面是没听老师讲之前写的,条件语句中内容过多,没有想到过关斩将的思想
                且我返回的是id 对应数组的下标
         */
//        int index = houseService.update(updateId);
//        if (index != -1) {
//            System.out.printf("姓名(" + houseService.getHouses()[index].getName() + "):");
//            String name = Utility.readString(5, "");
//            houseService.getHouses()[index].setName(name);
//            System.out.printf("电话(" + houseService.getHouses()[index].getPhone() + "):");
//            String phone = Utility.readString(11, "13588889999");
//            System.out.printf("地址(" + houseService.getHouses()[index].getAddress() + "):");
//            String address = Utility.readString(11, "中国***");
//            System.out.printf("租金(" + houseService.getHouses()[index].getRent() + "):");
//            int rent = Utility.readInt(1000);
//            System.out.printf("状态(" + houseService.getHouses()[index].getState() + "):");
//            String state = Utility.readString(3, "未出租");
//            System.out.println("--------------------------修改成功--------------------------");
//        } else {
//            System.out.println("-------------------------不存在该房屋-------------------------");
//        }
        House house = houseService.findById(updateId);
        if (house == null) {
            System.out.println("----------------------修改房屋信息的编号不存在----------------------");
            return;
        }
        System.out.printf("姓名(" + house.getName() + "):");
        String name = Utility.readString(5, "");
        if (!"".equals(name)) {//如果name非空,则修改
            house.setName(name);
        }
        System.out.printf("电话(" + house.getPhone() + "):");
        String phone = Utility.readString(11, "");
        if (!"".equals(phone)) {//如果name非空,则修改
            house.setPhone(phone);
        }
        System.out.printf("地址(" + house.getAddress() + "):");
        String address = Utility.readString(11, "");
        if (!"".equals(address)) {//如果name非空,则修改
            house.setAddress(address);
        }
        System.out.printf("租金(" + house.getRent() + "):");
        int rent = Utility.readInt(-1);
        if (rent != -1) {//如果name非空,则修改
            house.setRent(rent);
        }
        System.out.printf("状态(" + house.getState() + "):");
        String state = Utility.readString(3, "");
        if (!"".equals(state)) {//如果name非空,则修改
            house.setState(state);
        }
        System.out.println("--------------------------修改成功--------------------------");
    }
}
  1. HouseService.java
package com.wpangzi.houserent.service;

import com.wpangzi.houserent.domain.House;

/**
 * HouseService[业务层]
 * //定义House[],保存House对象
 * 1. 响应HouseView的调用
 * 2. 完成对房屋信息的各种操作(crud)
 */
public class HouseService {
    //属性
    /*
        1. 零钱通例子用到的是字符串拼接
        因为列表中属性显示的格式不是按照对象的属性来的,做了修改
        2. 房屋出租这个例子用的是数组
        因为列表中属性显示的格式就是按对象属性来的,直接用实体类中的toString方法输出即可
        toString方法重写 - 写成列表需要的格式
     */
    private House[] houses;//保存House对象
    private int houseNums = 2;//记录当前有多少个房屋信息
    private int idCounter = 2;//id计数器,记录当前id到哪个值

    //方法
    /*
        构造器
        1. House[]数组只初始化没有在堆中创建(因为不知道数组的大小)
        2. 当创建HouseService对象时,指定数组的大小
     */
    public HouseService(int size) {
        houses = new House[size];
        //为了配合测试,所以先初始化一个对象
        houses[0] = new House(1, "王胖子", "15800001111",
                "中国×××", 2000, "未出租");
        houses[1] = new House(2, "高瘦子", "13811115555",
                "平遥县", 1000, "已出租");
    }

    //list方法,返回houses数组
    public House[] list() {
        return houses;
    }

    //add方法,添加新对象,返回Boolean
    public boolean add(House newHouse) {
        //判断是否还可以继续添加(我们暂时不考虑数组扩容的问题)
//        if (houseNums == houses.length){//不能再添加
//            System.out.println("数组已满,不能再添加");
//            return false;
//        }
        //考虑数组扩容
        if (houseNums >= houses.length) {//调用数组扩容方法,数组扩1
            houses = copyHouse(houses);
        }
        /*
            把新增的房屋添加到数组中,然后houseNums加1
            第一种:
                houses[houseNums] = newHouse;
                houseNums++;
            第二种:
                houses[houseNums++] = newHouse;
         */
        houses[houseNums++] = newHouse;
        /*
            实现id自增长机制,然后更新newHouse的id
            第一种:
                 idCounter++;
                 newHouse.setId(idCounter);
            第二种:(先加后赋值)
                 newHouse.setId(++idCounter);

         */
        newHouse.setId(++idCounter);
        return true;
    }

    //实现数组扩容
    public House[] copyHouse(House[] houses) {
        House[] houses1 = new House[houses.length + 1];
        for (int i = 0; i < houses.length; i++) {
            houses1[i] = houses[i];
        }
        return houses1;
    }

    //del(),删除一个房屋信息
    public boolean del(int delId) {
        /*
            1. 应当先找到要删除的房屋信息对相应的下标
            2. 注意:下标和房屋编号不是一个东西(各司其职)
            3. houseNums是指现在有多少个房屋信息,比如有2个
            4. 而数组有多大,下标就有多少个,比如定义数组长度是10,则下标可以为10
         */
        int index = -1;//用于接收id对应数组的下标
        for (int i = 0; i < houseNums; i++) {//要删除的房屋(id),是数组下标未i的元素
            if (delId == houses[i].getId()) {
                index = i;
            }
        }
        if (index == -1) {//说明delId不存在
            return false;
        }
        /*
           1. 如果找到,则从下标index开始,每个元素前移,最后一个元素置空
              (这里的最后一个是指当前存在信息的最后一个)
           2. 后一个元素覆盖前一个,最后一个下标不参与循环,因为再加1就是空值或者越界了
           3. 删除之后要把houseNums--!!!
           3.1 第一种
                houses[houseNums-1] = null;
                houseNums --;//少一个
           3.2 第二种(这种自加加,自减减用很多的,如果要用到自增自减的要想到这个)
                houses[--houseNums] = null;
         */
        for (int i = index; i < houseNums - 1; i++) {
            houses[i] = houses[i + 1];
        }
        houses[--houseNums] = null;
        return true;
    }

    //findById(),返回House对象或者null
    public House findById(int findId) {
        /*
            findId和已有数据的id进行匹配,若匹配上则输出信息
            一定注意是和数组元素的id比较而不是和数组元素的下标比较!!!
            如果找到就返回这个house对象,如果没找到则返回空
            (比我那个返回当前下标然后使用get方法获取house对象的方法好)
         */
        for (int i = 0; i < houseNums; i++) {
            if (findId == houses[i].getId()) {
              return houses[i];
            }
        }
       return null;
    }
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是有关使用Spring Boot实现CRUD操作的增加、删除、修改和查询的一些基本步骤: 1. 配置项目依赖 在您的Maven或Gradle构建文件中添加Spring Boot和相关的数据库依赖。例如,如果您想要使用MySQL数据库,则需要添加以下依赖项: ```xml <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MySQL database driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ``` 2. 配置数据库连接 在application.properties或application.yml文件中添加数据库连接信息,如下所示: ```yaml spring.datasource.url=jdbc:mysql://localhost:3306/yourdatabase spring.datasource.username=yourusername spring.datasource.password=yourpassword spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update ``` 3. 创建实体类 创建一个实体类来表示您要持久化的数据。例如,如果您要创建一个用户对象,则可以编写以下代码: ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Column(name = "email") private String email; // getter and setter methods } ``` 4. 创建Repository接口 创建一个Repository接口来定义CRUD操作。例如,如果您要操作用户对象,则可以编写以下代码: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { } ``` 5. 创建服务类 创建一个服务类来实现您的业务逻辑。例如,如果您要实现用户管理功能,则可以编写以下代码: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> getAllUsers() { return userRepository.findAll(); } public User getUserById(Long id) { return userRepository.findById(id).orElse(null); } public User addUser(User user) { return userRepository.save(user); } public User updateUser(User user) { return userRepository.save(user); } public void deleteUserById(Long id) { userRepository.deleteById(id); } } ``` 6. 创建控制器类 创建一个控制器类来处理HTTP请求。例如,如果您要处理用户对象的HTTP请求,则可以编写以下代码: ```java @RestController @RequestMapping("/api/users") public class UserController { @Autowired private UserService userService; @GetMapping("") public List<User> getAllUsers() { return userService.getAllUsers(); } @GetMapping("/{id}") public User getUserById(@PathVariable("id") Long id) { return userService.getUserById(id); } @PostMapping("") public User addUser(@RequestBody User user) { return userService.addUser(user); } @PutMapping("") public User updateUser(@RequestBody User user) { return userService.updateUser(user); } @DeleteMapping("/{id}") public void好的,我可以用中文回答您关于 Spring Boot CRUD 的问题。 Spring Boot 是一个基于 Spring 框架的快速开发框架,可以帮助开发者快速构建 Web 应用程序。CRUD 则是指对于一个数据实体,可以进行增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)的操作。 在 Spring Boot 中实现 CRUD 操作,通常需要以下步骤: 1. 定义数据实体类:首先需要定义一个数据实体类,表示要进行 CRUD 操作的数据对象。该类需要使用 JPA 注解来定义实体和属性,并且需要定义一个主键属性。 2. 定义数据访问层接口:接下来需要定义一个数据访问层接口,用于定义数据操作的方法,包括增加、查询、更新和删除等操作。 3. 实现数据访问层接口:在实现数据访问层接口时,需要使用 Spring Data JPA 提供的 Repository 接口,该接口提供了许多 CRUD 操作的默认实现,可以大大减少我们的代码量。 4. 定义业务逻辑层接口和实现类:在定义业务逻辑层接口和实现类时,可以将数据访问层接口作为一个成员变量注入进来,并在业务逻辑层方法中调用数据访问层接口中的方法,来完成具体的数据操作。 5. 定义控制器类:最后需要定义一个控制器类,用于接收 HTTP 请求,并将请求参数传递给业务逻辑层进行处理,然后返回相应的结果给客户端。 以上就是实现 Spring Boot CRUD 的基本步骤,具体实现过程可以参考 Spring Boot 官方文档和相关教程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值