數據庫設計: 酒店訂房模塊
我的解決方案
一個思考過程的記錄:
大致上分爲兩種情況:
- 用戶預定房間
用戶在預定房間時,系統判斷當前空房信息,併爲其自動分配房間
預定了房間的顧客在入住的時候,直接入住之前分配的房間;如果對自動分配的房間號不滿意,可由前臺人員爲其手動選擇一個房間 - 用戶沒有預定房間直接入住
關鍵點來了,如何判斷用戶當前選中的房間類型在某一個時間段內是否還有空房呢?
我的想法是,在用戶預定或者入住的時候,將入住的房間號,開始時間,結束時間存入一張表中。在查詢空房信息時,輸入開始時間和結束時間,向這張表中查詢。
雖然在寫Service層的時候有點頭大,但終歸是寫出來了
具體說明篇幅有點長, 這裏不過多贅述
最後的數據庫ER圖是這樣的
老師的解決方案
老師的解決方法是真的妙,用了一個空房日曆表就解決了
利用定時事務,將所有房間類型和對應時間的空房數量存入一個空房日曆表
最後的ER圖
接口:查詢空房信息
數據準備
首先我在房型表中準備了三條數據
接着在套餐表中準備了幾條數據(注:我的套餐表命名是solution,老師的好像是叫room_price)
最後在空房日曆表中準備了幾條數據
由於三張表的關係是這樣的
三張表連接之後的數據量龐大,所以這裏不使用多表連接的方式來查詢數據
注意!我們的數據庫表的名稱不一定完全一樣!
model層
套餐實體類
@Data
public class Solution {
private Integer solutionID;
private String solutionName;
private Integer roomTypeID;
private String breakfastType;
private Double solutionPrice;
}
房型實體類
@Data
public class RoomType {
private Integer roomTypeID;
private String roomTypeName;
private String roomTypeDesc;
private String bedType;
private String wifiType;
private Integer startFloor;
private Integer endFloor;
}
空房日曆實體類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FreeRoomCalendar {
private Integer freeRoomCalendarID;
private Integer roomTypeID;
private Date calendarDate;
private Integer totalCount;
private Integer freeCount;
private Integer minFreeCount;
}
controller層
首先分析業務邏輯:
用戶輸入入住日期和退房日期, 查詢空房信息;
空房信息應該包括:【房型名稱,空房數量,套餐名稱,牀型,早餐類型,套餐價格】
由於返回空房信息的數據類型比較複雜,所以我們一般會有一個DTO層或者VO層來負責裝配這些數據。習慣原因,這裏我直接用VO層了;老師是分成了DTO層,無大礙
@Data
@NoArgsConstructor
@AllArgsConstructor
public class VoFreeRoom {
private String roomTypeName;
private Integer freeCount;
private String solutionName;
private String bedType;
private String breakfastType;
private Double solutionPrice;
}
@RestController
@RequestMapping("/roomOrder")
public class RoomOrderController {
@Autowired
private RoomService roomService;
@GetMapping("/freeRooms")
public ResultJson freeRoom(String checkInDate, String checkOutDate){
try {
//調用Service,傳入入住時間和退房時間取得空房信息
List<VoFreeRoom> voFreeRoomList = roomService.findFreeRoom(checkInDate,checkOutDate);
return new ResultJson("200","success",voFreeRoomList);
}catch (Exception e){
return new ResultJson("400","failed",null);
}
}
}
mapper層
在編寫具體業務邏輯之前,先來把涉及到的sql準備好吧
注:我的解決方案只是其中的一種,有可能有缺陷,如果大家發現有問題還望能提醒我
思路:
- 首先向空方信息表中查詢某個時間段中的房型的最小剩餘量, 並將結果按照房間類型分組顯示
對最小剩餘量的說明:假設1號剩5間房,2號剩3間房;客戶如果想要在1號和2號都入住的話,最多隻能給其分配3間房。
對應的sql語句
- 查詢所有的套餐信息
sql
- 查詢所有套餐對應的房間類型信息
由於套餐表中存有房間類型ID的外鍵,這裏有兩種方式,一種使用連接,一種使用通過外鍵查詢單條記錄,各有優劣,這裏我選用了後者
sql:
接下來就把這些SQL語句寫進mapper層
注意,在mapper的xml文件裏,特殊字符的表達: 大於號使用> 小於號使用<
空房信息mapper
@Mapper
public interface FreeRoomCalendarMapper {
List<FreeRoomCalendar> findFreeRooms(@Param("checkInDate") String checkInDate,@Param("checkOutDate")String checkOutDate);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.edu.fjzzit.web.myhotel.mapper.FreeRoomCalendarMapper">
<resultMap id="freeRoomCalendarMap" type="cn.edu.fjzzit.web.myhotel.model.FreeRoomCalendar">
<id column="free_room_calendar_id" jdbcType="INTEGER" property="freeRoomCalendarID" />
<result column="room_type_id" jdbcType="INTEGER" property="roomTypeID"/>
<result column="calendar_date" jdbcType="DATE" property="calendarDate"/>
<result column="total_count" jdbcType="INTEGER" property="totalCount"/>
<result column="free_count" jdbcType="INTEGER" property="freeCount"/>
<result column="MIN(free_count)" jdbcType="INTEGER" property="minFreeCount"/>
</resultMap>
<select id="findFreeRooms" resultMap="freeRoomCalendarMap">
SELECT room_type_id,MIN(free_count) as free_count
FROM free_room_calendar
WHERE calendar_date >= #{checkInDate}
AND calendar_date < #{checkOutDate}
GROUP BY room_type_id
</select>
</mapper>
房型Mapper,套餐Mapper:略
service層
最後就是業務層了
用戶查詢時候輸入入住時間和退房時間,返回的是每種套餐的具體信息和剩餘房間數量
思路:
- 查詢所有套餐信息
- 通過入住日期和退房日期查詢空房信息
- 遍歷套餐信息,通過套餐信息中的房型ID外鍵查詢房型信息
- 在每次遍歷套餐信息的過程中,再對空房信息進行遍歷,把房型ID相同的添加到VO層中
解釋起來有點費勁,直接看代碼吧!
RoomService
public interface RoomService {
List<VoFreeRoom> findFreeRoom(String checkInDate,String checkOutDate);
}
RoomServiceImpl
@Service
public class RoomServiceImpl implements RoomService {
@Autowired
private FreeRoomCalendarMapper freeRoomCalendarMapper;
@Autowired
private SolutionMapper solutionMapper;
@Autowired
private RoomTypeMapper roomTypeMapper;
@Override
public List<VoFreeRoom> findFreeRoom(String checkInDate, String checkOutDate) {
List<VoFreeRoom> voFreeRoomList = new ArrayList<>();
//查詢所有的套餐
List<Solution> solutionList = solutionMapper.findAllSolutions();
//通過開始日期和結束日期先去空房日曆表中查詢最小空房數量
//操作mapper層
//從日曆表中查詢得到空房的房間類型和空房數量
List<FreeRoomCalendar> freeRoomCalendarList = freeRoomCalendarMapper.findFreeRooms(checkInDate,checkOutDate);
//遍歷所有套餐
for(Solution solution:solutionList){
//遍歷空房日曆結果
for(FreeRoomCalendar freeRoomCalendar:freeRoomCalendarList){
//將符合套餐的房間類型裝填進Vo層中
if(freeRoomCalendar.getRoomTypeID()==solution.getRoomTypeID()){
//取出根據套餐中的房型ID房型信息
RoomType roomType = roomTypeMapper.findFirstRoomTypeByID(solution.getRoomTypeID());
String roomTypeName = roomType.getRoomTypeName();
Integer freeCount = freeRoomCalendar.getFreeCount();
String solutionName = solution.getSolutionName();
String bedType = roomType.getBedType();
String breakfastType = solution.getBreakfastType();
Double solutionPrice = solution.getSolutionPrice();
voFreeRoomList.add(new VoFreeRoom(roomTypeName,freeCount,solutionName,bedType,breakfastType,solutionPrice));
}
}
//voFreeRoomList.add(new VoFreeRoom("",0,"","","",0.0));
}
return voFreeRoomList;
}
}
測試接口
嘗試查詢 2019-11-09 ~ 2019-11-11的空房信息