1. 基本的数据库表
-
教室基本信息表 classroom_baseinfo
labelName description classroomName 教室名称 classroomType 多功能教室、普通教室、公共机房、阶梯教室、专业机房等 classroomLevel 院级、校级 classroomHold 教室的容量 -
教室状态表 classroom_status
labelName description classroomName 教室名称 zc 周次,24位数 ,011111111111111111000000; 或者 011111111111111_1100_0_0(下划线表示空闲) xqj 1~7周1到周7 djdj 1~5 1到5大节 classroomType 多功能教室、普通教室、公共机房、阶梯教室、专业机房 classroomLevel “院级"或者"校级” classroomStatus “被占用"或者"空闲中” classroomHold 教室的容量 classroomInfo 暂时没用的字段
该表最初由两部分构成:
1.所有的教室信息(239条),其中zc设置为’0’,xqj和djdj设置为0,classroomName设置为其教室的名称。
2.课表改造出来的教室状态记录(7k多条)。
2. 查询逻辑
2.1 根据7个参数查询出某个时候某个的所有教室状态【链表合并+去重】
- 参数
星期几xqj ,这个参数主要用于来确定筛选时间
第几大节djdj, 这个参数主要用于确定筛选时间
周次zc,这个参数主要用于确定筛选时间
教室类型classroomType,这个参数主要是用来筛选教室类型的(多功能教室等)
教室级别classroomLevel,这个参数主要是用来筛选院级教室或者校级教室的
教室区域classroomArea,这个参数主要是用来筛选教室位置的。
参与人数attenderNum, 这个参数主要用用来筛选教室的容量的。
- 算法步骤:
Step1: 初始化教室状态链表list1和list2,讲它们置为空链表
Step2: 查询出符合所有要求(7个参数, 调用findAllBySevenCondition接口)的教室状态,并将结果链表赋值给list1。这样做的目的是查询出所有已经存在的教室状态,如被上课占用 或者 被申请占用的教室。比如博学楼的所有满足时间需求、容量需求的教室。
Step3: 查询出符合地点、容量、类型、级别的教室状态(4个参数,调用findAllByFourCondition接口),并将结果链表赋值给list2。这样做的目的是查询出所有满足地理空间条件的教室状态,以便为链表去重做准备(list2包含list1)。比如博学楼的所有满足容量需求的教室。list2中的状态元素的zc属性全为’0’
Step4: 把list2的元素全部放到list1中去,并准备一个hash表<ClassroomName, 1或者0>以备去重
Step5: 开启循环操作,判断是否已经遍历到链表的末尾了,如果是,则跳到Step9;否则进入下一步
Step6: 获取当前教室状态元素,判断教室状态元素的zc(周次)属性是否为’0’。如果该状态的zc属性不为’0’,说明这个教室的状态记录是存在于数据库表中的,那么使用hash表给该教室的名称标记上已存在(置为’1’),跳到Step8。如果为’0’,说明这个教室状态记录是教室本身的状态信息,进入Step7
Step7: 尝试从hash表中获取该教室状态元素的标记,如果获取的标记为‘1’,那么说明之前标记过,也即之前存在这个状态,所以这里就删除该为zc为’0’的元素。如果获取的标记为’0’,那么将这个教室状态的zc、xqj、djdj设置为查询参数的值,然后把classroomStatus字段设置为“空闲中”。
Step8:获取下一个链表元素
Step9: 返回去重后的list1并结束
时间复杂度O(m + n),m指所有满足空间条件的所有教室的数量,n指所有满足时间、空间条件已在数据库中存在记录的教室数量。
分析:查询出来的结果,会显示一部分被占用(之前存在的状态)、一部分空闲(剩下的教室状态)
代码:
public List<ClassroomStatus> getQueryList(String classroomType,String classroomArea,int classroomHold,String zc,int xqj,int djdj,String classroomLevel){
List<ClassroomStatus> list1=null;
List<ClassroomStatus> list2=null;
List<ClassroomStatus> ans=null;
/*查询符合所有要求的教室*/
list1=statusDao.findAllBySevenCondition(classroomType,classroomArea,classroomHold,zc,xqj,djdj,classroomLevel);
/*把所有符合时间、地点、容量、类型的教室都查出来*/
list2=statusDao.findAllByFourCondition(classroomType,classroomArea,classroomHold,classroomLevel);
/*把符合地点、容量、类型要求的教室都找了出来*/
list1.addAll(list2);
Map<String,Integer> map=new HashMap<String,Integer>();
for(int i=0;i<list1.size();i++){
ClassroomStatus item=list1.get(i);
if(!"0".equals(item.getZc())){
map.put(item.getClassroomName(),1);
}else{
Integer tmpMapVal=map.get(item.getClassroomName());
if(tmpMapVal!=null && tmpMapVal==1){
list1.remove(item);
i--;/*这里一定要注意*/
}else{
item.setZc(zc);
item.setXqj(xqj);
item.setDjdj(djdj);
item.setClassroomStatus("空闲中");
list1.set(i,item);
}
}
}
return list1;
}
-
Mapper层接口 与 sql语句
-
public List<ClassroomStatus> findAllBySevenCondition(String classroomType,String classroomArea,int classroomHold,String zc,int xqj,int djdj,String classroomLevel);
<select id="findAllBySevenCondition" resultType="com.SpringBoot1.entity.ClassroomStatus"> select * from classroom_status where classroomType=#{classroomType} and classroomName like "%"#{classroomArea}"%" and classroomHold>=#{classroomHold} and zc like #{zc} and xqj=#{xqj} and djdj=#{djdj} and classroomLevel=#{classroomLevel} </select>
-
public List<ClassroomStatus> findAllByFourCondition(String classroomType,String classroomArea,int classroomHold,String classroomLevel);
<select id="findAllByFourCondition" resultType="com.SpringBoot1.entity.ClassroomStatus"> select * from classroom_status where classroomType=#{classroomType} and classroomName like "%"#{classroomArea}"%" and classroomHold>=#{classroomHold} and zc="0" and classroomLevel=#{classroomLevel} </select>
-
2.2 根据4个主键查询出某个教室的在某个时候的具体状态
- 参数
(1)教室名称classroomName
(2)星期几xqj
(3)第几大节djdj
(4)周次zc
3. 增加逻辑(增加"被占用"状态)
3.1 Mapper层接口与sql语句
/*通过三个主键查找是否存在这个教室状态,重载,上面那个是为了获取一个教室的状态*/
public ClassroomStatus findStatusByThreeKeyColumns(String classroomName,int xqj,int djdj);
<select id="findStatusByThreeKeyColumns" resultType="com.SpringBoot1.entity.ClassroomStatus">
select * from classroom_status where classroomName=#{classroomName} and xqj=#{xqj} and
djdj=#{djdj}
</select>
/*插入这个教室状态*/
public int insertIntoClassroomStatus(ClassroomStatus classroomStatus);
<insert id="insertIntoClassroomStatus" >
insert into classroom_status values
(#{classroomName},#{zc},#{xqj},#{djdj},#{classroomType},#{classroomLevel},#{classroomStatus},#{classroomHold},#{classroomInfo})
</insert>
/*修改周次*/
public int updateClassroomStatus(ClassroomStatus classroomStatus);
<update id="updateClassroomStatus">
update classroom_status set classroomStatus=#{classroomStatus},classroomInfo=#{classroomInfo},zc=#{zc} where
classroomName=#{classroomName} and xqj=#{xqj} and djdj=#{djdj}
</update>
3.2 Service层
关键api:public int saveToClassroomStatus(ClassroomStatus classroomStatus){}
大概逻辑:先执行查询(根据教室名称、星期几、第几大节),如果数据库中没有记录,那么则执行添加操作 ;如果有记录,那么执行修改操作。
其中:
"在classroom_status表中查询是否存在某教室某时间"被占用"的记录"即为statusDao.findStatusByThreeKeyColumns();
"执行修改操作,将zc字段字符串的某位置设置为’_’ "对应着ZcUtil.getNewZcByOldZc(newZc,oldZc) 。
代码:
public int saveToClassroomStatus(ClassroomStatus classroomStatus){
ClassroomStatus flag=statusDao.findStatusByThreeKeyColumns(classroomStatus.getClassroomName(),classroomStatus.getXqj(),classroomStatus.getDjdj());
if(flag==null){
System.out.println("进入insert");
classroomStatus.setClassroomStatus("被占用");
statusDao.insertIntoClassroomStatus(classroomStatus);
return 0;
}else{
System.out.println("进入update");
String oldZc=flag.getZc();
String newZc=classroomStatus.getZc();
newZc= ZcUtil.getNewZcByOldZc(newZc,oldZc);
classroomStatus.setZc(newZc);
classroomStatus.setClassroomStatus("被占用");
statusDao.updateClassroomStatus(classroomStatus);
return 1;
}
}
ZcUtil.getNewZcByOldZc(newZc,oldZc)的实现代码:
/**
* 举例:
* newZc ____________________1___ 24位
* oldZc ____________1___________ 24位
* 期望返回的结果:
* resZc ____________1_______1___ 24位
* @param newZc
* @param oldZc
* @return
*/
public static String getNewZcByOldZc(String newZc,String oldZc){
int i;
char temp[]=oldZc.toCharArray();
for(i = 0; i < MAXZC; i ++){ /*MAXZC是类成员变量,MAXZC = 24*/
if(newZc.charAt(i) == '1'){
temp[i] = '1';
break;
}
}
// String ans= Arrays.toString(temp).replaceAll("[\\[\\]\\s,]","");
String ans = String.valueOf(temp);//上面那句话效果等价于这一句话
return ans;
}
4. 修改逻辑(“被占用”->“空闲中”)
4.1 Mapper层与sql
同增加逻辑,即:一是根据三个关键字查询数据库中存在的信息(通过调用findStatusByThreeKeyColumns方法),二是将信息存入数据库中(通过调用updateClassroomStatus方法)。
/*通过三个主键查找是否存在这个教室状态,重载,上面那个是为了获取一个教室的状态*/
public ClassroomStatus findStatusByThreeKeyColumns(String classroomName,int xqj,int djdj);
<select id="findStatusByThreeKeyColumns" resultType="com.SpringBoot1.entity.ClassroomStatus">
select * from classroom_status where classroomName=#{classroomName} and xqj=#{xqj} and djdj=#{djdj}
</select>
/*修改周次*/
public int updateClassroomStatus(ClassroomStatus classroomStatus);
<update id="updateClassroomStatus">
update classroom_status set classroomInfo=#{classroomInfo}, zc=#{zc} where
classroomName=#{classroomName} and xqj=#{xqj} and djdj=#{djdj}
</update>
4.2 Service层
其中:
"在classroom_status表中查询是否存在某教室某时间"被占用"的记录"即为statusDao.findStatusByThreeKeyColumns();
"执行修改操作,将zc字段字符串的某位置设置为’_’ "对应着ZcUtil.setKongXianZc(newZc,oldZc)。
public int setFreeClassroomStatus(ClassroomStatus classroomStatus){
ClassroomStatus flag=statusDao.findStatusByThreeKeyColumns(classroomStatus.getClassroomName(),classroomStatus.getXqj(),classroomStatus.getDjdj());
if(flag==null){
return 0;
}else{
String oldZc=flag.getZc();
String newZc=classroomStatus.getZc();
newZc= ZcUtil.setKongXianZc(newZc,oldZc);
classroomStatus.setZc(newZc);
return statusDao.updateClassroomStatus(classroomStatus);
}
}
5. 删除逻辑 ~ 同修改逻辑
删除某个状态,等价于将某个状态置为空闲。
如果某记录的周次字段全为下划线,那么可以将该记录删除掉,通过定位"classroomName" and “xqj” and “djdj”