这两天完成了项目中的一个不是很大的功能实现,功能虽小,但是暴露出较多的问题.在这里做简单记录总结.
功能简述
器具受检率统计是一个实体,有一个年份字段,器具每年可以受检也可以不检.由于新的一年,器具的基本信息都不会改变,但是器具要重新统计是否受检,所以受检总数变为0.由于大部分的字段都不用改变,所以需要一个clone方法,clone上一年份的所有信息,然后将年份和受检总数重新设置.
实现构想
获取系统当前年份,进而求得上一年年份
根据年份获取上一年的所有记录
遍历所有记录,将年份重置为今年年份,受检总数重置为0,其他属性直接复制
遇到的问题
(一)如何获取所有记录?
第一想法,for循环.但马上就被自己否掉了.数据少还可以,但是数据多了呢?显然不切实际,那么如何能一下子将所有的记录都直接取出来呢?
解决办法
在对应的repository上直接添加函数 findAllByYear:
|
|
这是一个Spring Data JPA提供给我们的查询策略,这里不做详细解释,参考https://docs.spring.io/spring-data/jpa/docs/2.0.5.RELEASE/reference/html/#jpa.query-methods.query-creation
(二)如何获取大量数据
在获取大量数据时,当数据量达到十万级百万级,显然我们再一下子或去除所有的信息就显得行不通了.这么大量的数据量必然会造成数据库卡顿甚至崩溃.
解决办法
分组获取.我们将对应的信息进行一个分组,将直接全部获取变为批量获取,这样就能减小数据库的压力.同样的,我们还是再repository上建立分组获取的方法.
|
|
pageRequest 是用来limit的参数,它会控制批量获取数据.参考https://docs.spring.io/spring-data/commons/docs/current/api/
(三)如何进行单元测试?
既然我们设计了要获取大量的数据,所以我们就要测试一下在较多的数据下的情况.所以我们要创建多组数据.然后在执行Clone方法后如何判断方法执行成功?
解决办法
首先,插入大量数据这点还没有一个较好的解决办法,只是用循环逐条插入,虽然效率较低,但是,我们此单元测试的主要功能并不是测试插入,所以这部分暂时搁置.
然后说一下我们如何判断方法执行成功.执行玩这个方法后,由于是按已有对象的克隆,所以首先就是要断言上一年分的对象依然存在.然后断言新的对象是否成功持久化.最后再判断新的对象的属性是否都成功赋值.
|
|
代码重构
方法功能虽然实现了,但是再代码结构不清,比较混乱重复代码较多.所以这就急需重构代码.
公共函数提炼
克隆部分是最多但是都是重复的代码,而且以后很有可能还会使用这个方法,所以选择将其提炼成一个公共函数,克隆自身.
|
|
函数逻辑重构
开始定义多个变量用来实现控制分组获取数据,但是变量一多,就显得结构不够清晰,而且也不利于代码的修改,不方便阅读.修改逻辑后,只选择使用一个变量,用来判断是否为最后一页,直到最后一页循环停止.最后,在保存的时候,不要每复制完一个对象都保存一次,应该是在复制完一组之后,将整组批量存入.这样会减少访问数据库的次数.
|
|
总结
每一个小的功能实现都不是简单的思考就可以实现的.勤思,会为你后面的大功能做思维的铺垫;规范,会让你的代码结构清晰.