支线任务卡:010404-JDBC-航班系统

通过JDBC实现一个航班系统

一、任务要求

1、创建数据库表 airinfo,添加测试数据不少于 4 条。要求主键自增

在这里插入图片描述

2、创建实体类 AirInfo,根据业务提供需要的构造方法和setter和getter方法。

package bean;


public class AirInfo {
    private int no;
    private String airId;
    private String destination;
    private String flyDate;

    @Override
    public String toString() {
        return no + "\t\t" + airId +"\t\t\t"+ destination +"  \t\t"+ flyDate;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getAirId() {
        return airId;
    }

    public void setAirId(String airId) {
        this.airId = airId;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    public String getFlyDate() {
        return flyDate;
    }

    public void setFlyDate(String flyDarete) {
        this.flyDate = flyDarete;
    }
}

3、创建 BaseDao 类,实现数据库连接和关闭功能。

(1)配置.properties文件

将数据库连接需要重复用到的信息配置为属性文件,命名为db.properties。如果后续要更改数据库或者链接地址更换的话,直接在这个文件里该数据就行,十分方便。

driver = com.mysql.cj.jdbc.Driver
uname = root
upass = 123456
url = jdbc:mysql://localhost:3306/yhp?serverTimezone=UTC

(2)建立Druid连接池,获取配置文件,实现数据库的连接

package util;

import bean.AirInfo;
import com.alibaba.druid.pool.DruidDataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

public class BaseDao {

    private Connection connection = null;
    private PreparedStatement pps = null;
    private ResultSet result = null;
    private int count = 0;//接收受影响行数

    private static String userName;
    private static String passWord;
    private static String url;//连接数据库的地址
    private static String driverName;
    //引入Druid(德鲁伊)连接池
    private static DruidDataSource dds = new DruidDataSource();

    //初始化
    static {
        // 1.加载属性文件
        ResourceBundle bundle = ResourceBundle.getBundle("db");
        driverName = bundle.getString("driver");
        url = bundle.getString("url");
        userName = bundle.getString("uname");
        passWord = bundle.getString("upass");
        // 2.设置参数
        dds.setUsername(userName);
        dds.setPassword(passWord);
        dds.setUrl(url);
        dds.setDriverClassName(driverName);

    }

    /**
     * 建立连接,设为protected是为了方便让子类继承
     *
     * @return
     */
    protected Connection getConnection() {
        try {
            connection = dds.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return connection;
    }

    /**
     * 根据传入的sql语句建立预状态通道pps
     *
     * @param sql  传入的sql语句
     * @param list 存放填充占位符的数据
     * @return
     */
    protected PreparedStatement getPps(String sql, List list) {
        try {
            pps = getConnection().prepareStatement(sql);
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    pps.setObject(i + 1, list.get(i));
                }
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return pps;
    }

    /**
     * 启用pps,实现增删改的功能
     *
     * @param sql
     * @param list
     * @return
     */
    protected int update(String sql, List list) {
        pps = getPps(sql, list);
        try {
            count = pps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return count;
    }

    /**
     * 启用pps,实现查询的功能
     *
     * @param sql
     * @param list
     * @return
     */
    protected ResultSet query(String sql, List list) {
        pps = getPps(sql, list);
        try {
            result = pps.executeQuery();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return result;
    }

    /**
     * 执行查询结果集的处理
     *
     * @param sql
     * @param list
     * @return
     */
    public List<AirInfo> dealSelect(String sql, List list) {
        List<AirInfo> airs = new ArrayList<>();//用于存放查询出的信息表
        try {
            ResultSet result = query(sql, list);//若没有占位符,则直接传null就可以
            while (result.next()) {
                //为当前对象的各属性赋值
                AirInfo air = new AirInfo();
                air.setNo(result.getInt("no"));
                air.setAirId(result.getString("airId"));
                air.setDestination(result.getString("destination"));
                air.setFlyDate(result.getString("flyDate"));
                //将赋值完毕的对象存入airs集合中
                airs.add(air);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            closeAll();
        }
        return airs;
    }

    protected void closeAll() {
        try {
            if (connection != null) {
                connection.close();
            }
            if (pps != null) {
                pps.close();
            }
            if (result != null) {
                result.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }


}

4、创建 Dao 接口 AirInfoDao,定义查询所有航班,按日期和目的地查询航班,删除航班,更新航班的方法。

package dao;

import bean.AirInfo;

import java.util.List;

public interface AirInfoDao {
    // 1.列出所有航班,
    public List<AirInfo> getAll();
    // 2.按起飞时间查询,
    public List<AirInfo> getByDate(String date);
    // 3.按目的地查询,
    public List<AirInfo> getByDes(String des);
    // 4.删除航班(根据编号),
    public int delete(int no);
    // 5.更新航班,
    public int updateByNo(AirInfo air);
//    // 6.离开系统
//    public void away();

    public List<AirInfo> getByNo(int no);
}

5、创建DAO实现类AirInfoDaoImpl,继承BaseDao类,实现AirInfoDao接口,使用 JDBC 完成相应数据库操作。

package dao.impl;

import bean.AirInfo;
import dao.AirInfoDao;
import util.BaseDao;

import java.util.ArrayList;
import java.util.List;

public class AirInfoDaoImpl extends BaseDao implements AirInfoDao {
    //定义变量
    private String sql = null;//用于传达各种指令
    private List list = new ArrayList();//用于存放填充占位符的数据
    int count;//记录受改变的行数

    /**
     * 1.列出所有航班信息,
     *
     * @return
     */
    @Override
    public List<AirInfo> getAll() {
        sql = "select * from airInfo";//查询语句(所有航班)
        return dealSelect(sql, list);//处理查询,返回结果集
    }

    /**
     * 2.按起飞时间查询,
     *
     * @param date
     * @return
     */
    @Override
    public List<AirInfo> getByDate(String date) {
        sql = "select * from airInfo where flyDate = ?";//查询语句(同一起飞日期)
        list.add(date);//传入等待检查的日期,准备填充占位符
        return dealSelect(sql, list);//处理查询,返回结果集
    }

    /**
     * 3.按目的地查询,
     *
     * @param des
     * @return
     */
    @Override
    public List<AirInfo> getByDes(String des) {
        sql = "select * from airInfo where destination = ?";//查询语句(同一目的地)
        list.add(des);//传入等待检查的日期,准备填充占位符
        return dealSelect(sql, list);//处理查询,返回结果集
    }

    //4.删除航班(根据编号),
    @Override
    public int delete(int no) {
        sql = "delete from airInfo where no = ?";
        list.add(no);
        count = update(sql, list);
        return count;
    }

    @Override
    public int updateByNo(AirInfo air) {
        sql = "update airInfo set airId = ?,destination = ?,flyDate = ? where no = ?";
        list.add(air.getAirId());
        list.add(air.getDestination());
        list.add(air.getFlyDate());
        list.add(air.getNo());
        count = update(sql,list);
        return count;
    }

//    @Override
//    public void away() {
//
//    }

    @Override
    public List<AirInfo> getByNo(int no) {
        sql = "select * from airInfo where no = ?";
        list.add(no);
        return dealSelect(sql, list);
    }
}

6、创建 Main 类,完成在控制台显示留言信息和用户添加留言操作,启动

(1)创建菜单类Menu,实现从控制台到Dao的交流

package test;

import bean.AirInfo;
import dao.AirInfoDao;
import dao.impl.AirInfoDaoImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Menu {
    //定义变量
    private AirInfoDao dao = new AirInfoDaoImpl();//用于执行具体的数据库操作
    private List<AirInfo> airs = new ArrayList<>();//用于接收和返回的信息表
    private AirInfo air = new AirInfo();//用于迭代的单个信息
    private Scanner input = new Scanner(System.in);//用于接收用户的输入

    /**
     * 构造器,用于接收用户传入的指令并进行跳转或提示
     *
     * @param in
     */
    public Menu(int in) {
        switch (in) {
            case 1:
                case_1();
                break;
            case 2:
                case_2();
                break;
            case 3:
                case_3();
                break;
            case 4:
                case_4();
                break;
            case 5:
                case_5();
                break;
            case 6:
                break;
        }
    }

    // 1.列出所有航班,
    public void case_1() {
        System.out.println("------------------所有航班信息如下------------------");
        airs = dao.getAll();
        printAir();
    }

    // 2.按起飞时间查询,
    public void case_2() {
        System.out.println("请输入您要查询的起飞时间(如:2021-3-10):");
        String date = input.next();//用户输入日期
        airs = dao.getByDate(date);//根据日期查询所有符合条件的航班
        System.out.println("----------于" + date + "起飞的航班信息如下--------------");
        printAir();//将查询到的航班信息打印出来
    }

    // 3.按目的地查询,
    public void case_3() {
        System.out.println("请输入您要查询的目的地(如:成都):");
        String des = input.next();//用户输入目的地
        airs = dao.getByDes(des);//根据目的地查询所有符合条件的航班
        System.out.println("----------飞往" + des + "的航班信息如下--------------");
        printAir();
    }

    // 4.删除航班(根据编号),
    public void case_4() {
        System.out.println("请输入您要删除的航班编号:");
        int no = input.nextInt();
        airs = dao.getByNo(no);
        System.out.println("----------编号为" + no + "的航班信息如下--------------");
        printAir();
        System.out.println("是否确定删除(输入1或0):");
        if (input.nextInt() == 1) {
            int isDel = dao.delete(no);
            if (isDel > 0) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败,请检查!");
            }
        }
    }


    // 5.更新航班,
    public void case_5() {
        //接收用户输入的新信息
        System.out.println("请输入需要更新的航班编号:");
        air.setNo(input.nextInt());
        System.out.println("请输入新的航班号");
        air.setAirId(input.next());
        System.out.println("请输入新的目的地");
        air.setDestination(input.next());
        System.out.println("请输入新的起飞日期");
        air.setFlyDate(input.next());
        //用新信息覆盖旧信息
        int i = dao.updateByNo(air);
        if (i > 0) {
            System.out.println("更新成功");
        } else {
            System.out.println("更新失败");
        }
    }

//    // 6.离开系统
//    public void away() {
//
//
//    }

    /**
     * 打印航班信息
     */
    public void printAir() {
        if (airs != null && airs.size() > 0) {
            System.out.println("编号\t航班号\t\t目的地\t\t起飞日期");
            for (int i = 0; i < airs.size(); i++) {
                air = airs.get(i);
                System.out.println(air);
            }
        }
    }
}

(2)创建Main类,实现与Menu的互动

package test;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        System.out.println("--------------欢迎使用航班信息管理系统--------------");

        while (true) {
            System.out.println("请选择操作(1.列出所有航班,2.按起飞时间查询,3.按目的地查询,4.删除航班,5.更新航班,6离开系统):");
            Scanner input = new Scanner(System.in);
            int in = input.nextInt();
            new Menu(in);
        }


    }
}

二、运行结果示例

请添加图片描述

三、改进与反思

1、问题

在进行其他选项的测试时都达到了目的,但是在进行删除操作时系统报了个越界的错
在这里插入图片描述
出错的代码在这个位置(下图打断点的那一行)
在这里插入图片描述
一开始我觉得问题是不是出在参数设置上了,可是我就是专门写成i+1的呀怎么可能会出错?后来我试了好多遍就是不对,回去看了教材和视频也证明这行代码确实没毛病。那么问题出在了哪里?
于是我断点调试了好久才发现在进入delete函数之后,list的元素竟然多了一个!这时我才恍然大悟:问题出在下面打出断点的位置!

在这里插入图片描述

查询航班信息的时候我们调用了getByNo方法已经往list里面填了一个编号了,在delete里面只要再把list拿出来用一次就行了,不用再次添加了。

2、反思

(1)所以这个问题其实出在二次赋值,导致list中有两个重复的no,但是需要填充的占位符只有一个,才会出现所谓的越界提示。

(2)经过测试,原先错误的代码也可以将目的航班删除,但这种写法太不严谨,远达不到可交付的级别。

(3)不能机械地认为每一个函数都应该传参,都应该按同一套流程走,如果是这样又何必写那么多不一样的函数呢,直接抽象出一个新的函数,要用的时候直接调不是更省事吗?写代码要动脑子!!!

3、代码对比

最后贴一下改正前后的对比吧(这些代码原来的所在已经标注清楚,错误的地方已通过注释说明)

	//接口AirInfoDao中第15行的改动:将参数删去
    public int delete();

   //实现类AirInfoDaoImpl中第55、57行的改动:删去参数,删去第二次在list中插入元素的语句
    @Override
    public int delete() {//这里的参数用不上,也不用传了
        sql = "delete from airInfo where no = ?";
        //因为在删除只前已经查询过一遍了(list里面已经有值了),所以无须二次赋值,直接传就可以
        //list.add(no);
        count = update(sql, list);
        return count;
    }

    // 菜单类Menu中第79行的改动:调用delete不再传参
    public void case_4() {
        System.out.println("请输入您要删除的航班编号:");
        int no = input.nextInt();
        airs = dao.getByNo(no);//这个地方list已经赋值了,通过list就能查到对应的航班
        System.out.println("----------编号为" + no + "的航班信息如下--------------");
        printAir();
        System.out.println("是否确定删除(输入1或0):");
        if (input.nextInt() == 1) {
            int isDel = dao.delete();//这个地方直接借用上面查到的数据就行,不用再传参数
            if (isDel > 0) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败,请检查!");
            }
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值