第三个项目:HMS(宾馆管理系统)
一.在使用REPLACE可以同时实现INSERT和UPDATE的功能,不过有以下需要注意的地方
REPLACE=INSERT+UPDATE(有点像)
关于REPLACE和INSERT的区别,REPLACE要求主键只能够有一条
根据应用情况可以使用replace 语句代替insert/update语句。例如:如果一个表在一个字段上建立了唯一索引,当向这个表中使用已经存在的键值插入一条记录,将会抛出一个主键冲突的错误。如果我们想用新记录的值来覆盖原来的记录值时,就可以使用REPLACE语句。
使用REPLACE插入记录时,如果记录不重复(或往表里插新记录),REPLACE功能与INSERT一样,如果存在重复记录,REPLACE就使用新记录的值来替换原来的记录值。使用REPLACE的最大好处就是可以将DELETE和INSERT合二为一,形成一个原子操作。这样就可以不必考虑同时使用DELETE和INSERT时添加事务等复杂操作了。
在使用REPLACE时,表中必须有唯一有一个PRIMARY KEY或UNIQUE索引,否则,使用一个REPLACE语句没有意义。
注意:UPDATE和REPLACE的区别:
1)UPDATE在没有匹配记录时什么都不做,而REPLACE在有重复记录时更新,在没有重复记录时插入。
2)UPDATE可以选择性地更新记录的一部分字段。而REPLACE在发现有重复记录时就将这条记录彻底删除,再插入新的记录。也就是说,将所有的字段都更新了。
还有一点,如果表的字段中比较多的话,更新操作就最好使用UPDATE,精确的更新,如果使用REPLACE来更新的话,会将原先的记录删除,全部的字段更新,比较影响性能,还有,使用REPLACE的时候,需要前端传原先的全部数据(那前端该怎么获取原先的全部数据呢),所以还是需要根据实际情况来操作,
综上所述,对于选择使用REPLACE或UPDATE进行更新操作的建议:
-
如果字段比较多,使用REPLACE
-
如果数据更新的时候,非主键的其他属性需要全部更新的话,可以考虑使用REPLACE
-
如果数据更新的时候,主键也需要更新,使用REPLACE
-
实际上,更新操作的时候,其实还是主要是用UPDATE,因为使用REPLACE实现更新操作有一个致命的缺点:如果不想出现脏数据,那么更新时需要全部未修改的字段的原始数据,否则更新的时候,会导致无需修改的属性全部为NULL,部分数据将会被擦除,造成脏数据
其实REPLACE看起来像是万金油,但是其实使用的时候需要特别的注意,一不小心就有可能造成脏数据,所以使用的时候需要格外注意,能使用UPDATE的时候就尽量使用UPDATE,但是使用INSERT和REPLACE的话其实没有需要特别注意的地方
二.数据库中的一张表是否需要设置主键:看业务需求
-
如果涉及到了多表联合的时候,那每一张表都需要主键
-
如果只是简单的单表操作,每条数据可以重复,那么就不一定需要主键
三.Mybatis使用注解实现动态SQL
脚本实现
/**
* description:添加客房类型
*/
@Insert("<script>"
+ "UPDATE room_type "
+ "SET "
+ "<if test=\"type!=null and type!=\'\' \"> "
+ "type=#{type}, "
+ "</if> "
+ "<if test=\"price!=null\"> "
+ "price=#{price} "
+ "</if> "
+ "WHERE code=#{code} "
+ "</script> ")
boolean updateRoomType(RoomType roomType);
使用@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider
结构化实现SQL
但是这种自动生成的SQL和HIBERNATE一样,在实现一些复杂语句的SQL时会束手无策。所以需要根据现实场景,来考虑使用哪一种动态SQL
四.前后端时间戳传递机制
Long beginTime = MyNumberTranformUtil.getLong(dataCenterService.
getParamValueFromParamOfRequestParamJsonByParamName("beginTime"));
Long endTime = MyNumberTranformUtil.getLong(dataCenterService.
getParamValueFromParamOfRequestParamJsonByParamName("endTime"));
Date partBeginTime = null;
Date partEndTime = null;
if (beginTime != null) {
partBeginTime = new Date(beginTime.longValue());
}
if (endTime != null) {
partEndTime = new Date(endTime.longValue());
}
五.分页信息的传递机制
Integer pageNum = MyNumberTranformUtil.getInteger(dataCenterService.
getParamValueFromParamOfRequestParamJsonByParamName("pageNum"));
Integer pageSize = MyNumberTranformUtil.getInteger(dataCenterService.
getParamValueFromParamOfRequestParamJsonByParamName("pageSize"));
//检查分页信息
if (CheckVariableUtil.integerParamLessZero(pageNum) || CheckVariableUtil.integerParamLessZero(pageSize)
) {
ExceptionUtil.setFailureMsgAndThrow(ReasonOfFailure.PAGEINFO_ERROR);
return;
}
六.进行模糊查询的时候,最好将查询条件封装成一个类,使用JSON传递给后端,这样后端将会比较方便
七.尽量不要使用多层if-else嵌套
原代码,使用了多次的ifelse嵌套
//检查房间号是否为空
if (MyCheckUtil.isStringLegal(roomCode)) {
//检查客房信息是否存在
if (roomManagementDao.isRoomInfoExisted(roomCode)) {
//检查客房是否已预订
//检查客房是否已入住
dataCenterService.setData("roomCode",roomCode);
} else {
ExceptionUtil.setFailureMsgAndThrow(ReasonOfFailure.ROOM_IS_NOT_EXIST);
return;
}
} else {
ExceptionUtil.setFailureMsgAndThrow(ReasonOfFailure.ROOMCODE_IS_NULL);
return;
}
八.检查参数合法性工具类中,非法返回True,这样就可以避免使用的时候多做一次取反运算