Schwertlilien
As a recoder: notes and ideas.

数据库上机实验2~3

实验2,3

最重要的提醒!

如果你正开始写或者写了一半了,请务必牢记下面三点。

  1. 如果你传参的时候传了connection或是statement,不能在这个函数里close,不然你的主函数里就没法用了;
  2. 每一个statement都最好只对应一个SQL语句(不然你可能在半途把stmt.close())后面就不能使用了
  3. 最好用的工具try-catch(Exception e){e.printStackTrace();}可以快速定位到是哪里错了以及错误的原因;

血泪经验总结。然后,如果你还没开始写JDBC,建议去写MyBatis

一、实验要求

基于MySQL,设计并实现一个简单的旅行预订系统。该系统涉及的信息有航班、大巴班车、宾馆房间和客户数据等信息。其关系模式如下:

FLIGHTS (String flightNum, int price, int numSeats, int numAvail, String FromCity, String ArivCity);
HOTELS(String location, int price, int numRooms, int numAvail);
BUS(String location, int price, int numBus, int numAvail);
CUSTOMERS(String custName,custID);
RESERVATIONS(String custName, int resvType, String resvKey) ;

为简单起见,对所实现的应用系统作下列假设:

  1. 在给定的一个班机上,所有的座位价格也一样;flightNum是表FLIGHTS的一个主码(primary key)
  2. 同一个地方的所有的宾馆房间价格也一样location是表HOTELS的一个主码。
  3. 在同一个地方的所有大巴车价格一样;location是表 BUS的一个主码。
  4. custName是表CUSTOMERS的一个主码。
  5. RESERVATIONS包含着那些和客户预订的航班、大巴车或宾馆房间相应的条目,具体的说,resvType指出预订的类型(1为预订航班,2为预订宾馆房间,3为预订大巴车),而resvKey是表RESERVATIONS的一个主码。(这句话怎么理解?)
  6. 在表FLIGHTS中,numAvail表示指定航班上的还可以被预订的座位数。对于一个给定的航班(flightNum),数据库一致性的条件之一是,表RESERVATIONS中所有预订该航班的条目数加上该航班的剩余座位数必须等于该航班上总的座位数。这个条件对于表BUS和表HOTELS同样适用。

客户的名字竟是主码,是唯一不重复的;那么他的ID有什么用?身份证号吗?(暂且就这样吧);Bus、Hotel在某一location下只能有一家(主码约束)。

【关于reservation的分析】

for resvKey:与cust_nameresv_type合起来是reseveration的主码。

应用系统应完成如下基本功能:

  • 航班,大巴车,宾馆房间和客户基础数据的入库,更新(表中的属性也可以根据你的需要添加)。
  • 预定航班,大巴车,宾馆房间。
  • 查询航班,大巴车,宾馆房间,客户和预订信息。
  • 查询某个客户的旅行线路。
  • 检查预定线路的完整性。
  • 其他任意你愿意加上的功能。

二、关于数据约束的讨论

1.完整性约束

  • 对于reservation中的resvType取值只有:1,2,3。因此对于所有的reservation记录的resvType,若其值>3,那么该记录就不应存在。

    constraint limType check ( resvType>0 and resvType<4)

  • 对于reservation,bus,hotel:numXxx=numAvail+resveration中的记录条数

  • 对于flight中的FromCity不能等于ArivCity

2.主码约束

  • FLIGHTS (String flightNum, int price, int numSeats, int numAvail, String FromCity, String ArivCity);
  • HOTELS(String location, int price, int numRooms, int numAvail);
  • BUS(String location, int price, int numBus, int numAvail);
  • CUSTOMERS(String custName,custID);
  • RESERVATIONS(String custName, int resvType, String resvKey) ;
  1. 对于不同的航班来说,该航班号是唯一的。
  2. 对于同一location下,只能存在一家hotel记录。
  3. 对于同一location下,只能存在一家bus记录。
  4. 每位customer的名字custName一定是不同的。
  5. reseverations来说,其元素为resv_type,resv_key,cust_name,三者均可重复,但是三者组合起来作为serveration的主键,是唯一不重复的。

三、程序实现

1.实现功能

main函数要实现的功能:
1.添加fight,bus,hotel,customer数据-入库
2.添加reservation数据-入库-<会相应地变更其他数据库的内容,事务>
3.查询所有的数据-一键查询所有的数据?还是分开来写?
4.查询某用户的旅行路线–什么是旅行路线?指订的航班、酒店、大巴酱?
5.检查【预定线路】的完整性?–用户已预定,然后两地之间存在航班。

功能①:基本的增删改操作(for flight,bus,hotel,customer)

insert:好坑,就是使用PreparedStatement的时候,已经建立好sql语句后,应使用pstmt.executeUpdate()注意括号内无sql参数!

1
sql="insert into flights values(?,?,?,?,?)";

update

1
2
3
4
5
6
sql="update flights set price=?," +
"num_seats=?," +
"num_avail=?," +
"from_city=?," +
"ariv_city=?" +
"where flight_num=?";

delete

1
sql="delete from flights where flight_num=?"
功能②:基本的增删改操作(for reseveration)

预订航班、大巴车、宾馆房间。采用事务,原子性操作!

操作流程

  • 将事务自动提交设置为false
  • 先更改用户指定的预订的对应航班、大巴车、宾馆表的数据(num_avail变更);
  • 添加一条预订记录:正常在预订中insert数据。
  • 操作成功:事务提交;
  • 操作失败:事务回滚。
功能③:查询操作

就是显示数据,是十分简单的操作。

功能④:查某用户的旅行路线

操作流程:

  • 找到对应用户的reservations的信息,其中可能包括flight,hotel,bus的相关信息。
  • 分别对三者进行查询并归入list
  • 分别打印输出。
功能⑤:检查预定线路的完整性

对于题意的理解:对于特定的用户(给定用户的cust_name),查询其航班信息是否真实存在,即在flights表中找到相应的航班信息。

实现:在实现功能②向reservations中插入预订信息之前,首先需要对操作者输入的信息进行检查(是否在相应的表中存在数据)

2.扩展功能

操作者可能输入错误的数据,对于错误的数据会进入数据库中进行操作:

  • 对于该部分采用了异常处理,用户输入错误的信息并不会导致程序抛出异常而错误退出;而是由我进行异常的捕获并进行处理,并提醒用户输入了错误的信息。

之后可以进行扩展

  • 每一班的航班应当具有起飞时间-到达时间的信息;在超过了该预订日期之后会自动更新航班信息为新的日期以及全部可预订的座位;
  • 对于查询表格的信息,此处是以List形式打印;可以使用Java API中封装好的一些类进行优化;
  • 使用MyBatis(已封装)而不是JDBC(未封装,且易出现SQL注入问题)

四、功能验证

功能①

insert

update

记录一下:当时出现错误,就是PreparedStatementsql语句去给占位符赋值时搞错了顺序。然后很扯的事情来了,就是java会延迟,更新程序的部分并不能及时载入。(之前也这样过,得亏我想起来了)

delete

功能②

insert

update

感觉没什么用处,因此不考虑这个的实现。

delete

功能③

功能④

五、部分代码截图

test

Func1

Func2

Func3

Func4

搜索
匹配结果数:
未搜索到匹配的文章。