1:功能需求
该功能目标是将学生分配到指定的房间中,使用的是excel导入。
2:使用技术
主要技术是使用了我公司封装了SSH2的UT框架。excel的处理是使用了apache的poi,因为有同事封装好了读取数据的方法,所以对此没有做研究。
3:具体实现
前提:系统中有学生数据,且学生有考生号等的唯一标识,系统中有公寓楼和房间号,且公寓楼名称唯一,当前公寓楼下房间号不能重复。模板中包含学生标识,姓名,性别,公寓楼名称,房间号
(1):创建全局变量useRoomMap,addStuList,hasRoomStuList。其中useRoomMap为key是公寓楼+房间号,value为房间对象,该map的目的是记录在导入过程中影响了哪些房间,便于对房间进行维护,addStuList是保存导入的入住学生对象list,hasRoomStuList保存的是导入学生中在导入学生之前已经入住的入住学生对象。
(2):获取excel中的表头,检测表头每列的名称,判断是否是导入的指定模板。
(3):校验上传数据,检测是否有上传数据。
(4):在数据库中查询所有学生,并把学生数据使用key:唯一标识,value:学生对象保存在map中,这样做的目的是为了能够在进行数据校验的时候能快速的查找系统中是否有该学生。
(5):同第三步,查询所有的房间出来,并把房间数据使用key:公寓楼名+房间号,value:房间对象保存在map中,目的同第三步。
(6):循环导入的数据,进行数据校验。具体实现-->A:首先根据导入数据的唯一标识去查找学生集合中是否有该学生,如果有,则取出,如果没有,则将错误记录,B:将导入数据中的姓名和性别与从map中获取的学生进行对比,校验是否是匹配的,如果不匹配,则将错误记录,C:将导入数据中的公寓楼名称和房间号加起来查询房间map,查询是否有该房间,如果有,则获取,如果没有,则记录错误。D:将拿到的学生对象的性别和房间对象的性别进行比较,判断该学生性别是符合房间性别的,如果不符合,则记录错误数据。
(7):使用(6)中的房间key在useRoomMap中进行查找,如果没有找到房间对象,则将(6)中获取的房间对象的已用床位+1,并保存在useRoomMap中,如果找到了,就将获取到的房间对象的已用床位+1。做这一步的目的是记录房间已用床位数,便于之后检查房间的已用床位数大于了房间的可用床位数。
(8):如果在(6)中,能获取到学生对象和房间对象,则根据这两个对象生成一个学生入住对象,并保存在addStuList中
(9):在循环遍历校验完成后,使用获取的addStuList进行500条分组,组装成in(*,*,*。。。)的hql方式去查询学生入住表中的数据,获取到已经入住的入住学生对象集合,并且根据遍历入住学生集合,级联获取对应的房间对象,并且使用房间对象去查询useRoomMap是否有该房间,如果没有,则将当前查询的房间的已使用床位-1,保存到useRoomMap中,如果有,则将获取到的房间的已使用床位数-1。这样做的目的是因为导入前要清除导入学生的入住信息。
(10):遍历useRoomMap,检测每个房间的已使用床位是否大于可使用床位,如果大于,说明房间容量不足,记录该错误。
(11):如果前面10条完成后,错误记录的条数为不为0,则将错误信息返回到页面。如果没有错误信息,则进行下一步
(12):开始导入A:批量删除数据库中hasRoomStuList中的入住学生数据,B:批量将addStuList的学生导入数据库,C:循环遍历useRoomMap,根据每一个房间对象去查询该房间的入住学生和床位集合,并修改学生床位号和修改床位的入住状态。D,将每一个房间保存在一个List中,遍历完成后,批量更新房间信息。
4:功能总结
在编写该功能中,我在校验途中尽量避开hibernate的session缓存,所以这些校验都放在action层中,因为缓存中查询过多数据,会导致后面越来越慢。在第(12)步在导入时,将导入放在service中,并进行了事务控制,如果导入错误,能保证数据回滚,因为hasRoomStuList中的对象和addStuList中的对象有相同的id,所以在导入时出了异常,所以我在删除后进行了session.flush()与session.close()。总的来说,这个功能我做的不是很满意,因为在思考过程中感觉只想着如何把功能实现,没有考虑过多的性能,代码的优化,写出的代码感觉重用性不高。主要原因应该是自己知识水平还不足,写的时候没有考虑过设计模式等规则,对框架的使用还有欠缺。最后总结:下来要多多学习,将来写出性能高效,代码优美的程序。