MyBatis查询接口返回大量数据导致OOM
异常描述
- 接口调试过程中发现程序运行中断,DEBUG跟踪到Mapper中的查询接口报错,没有接收到返回值且抛出 out of memory 异常
异常定位
- 逐步DEBUG,对比传入底层的参数及最终的执行的SQL,发现WHERE条件均没有传参,即此时是全表查询,且数据量很大,导致了OOM异常的发生
异常反思
- 接口复用性:Mapper.java 是 DAO 层中接口,无论是 Service 层或 Business 层都会间接或直接的调用 Mapper.java 中的接口
- 除了使用MyBatis工具自动生产的接口外,其余接口均是为了开发某个功能时添加的,此时为了排序、为了某个特定值的传参或者有时候自己开发者觉得某个值肯定不会空,而没有使用 test 进行参数判空,其他开发人员在方法调用时直接根据接口名称和返回值就断定方法适合自己使用,而没有查看底层的Mapper.xml中的SQL实现,导致问题出现
- 特定功能开发的接口要通过名称注明,避免其他人误调用
- 共用的接口功能,通过 Map 或 PO 类作为参数的接口,每个属性都要加 test 判断,且需注意 order limit 与 属性条件使用顺序,避免报语法错误
- 查询接口一定要使用分页,调用接口前对入参进入处理,如果是集合,则拆分为500或1000一组,分批查询
OOM常见异常类型
- 开发过程中使用到的对象、集合,使用完毕后直接赋值为null,等待GC
- 避免对象不使用依然向下一个方法中传递
- 方法内的形参不使用时及时进行方法重构
- 可以改为在循环外声明对象,在循环内实例化对象,始终是同一个对象
- 可以改为克隆
- 用于存放各个方法的内部变量表
- 当大量的方法被调用,而又未及时结束,或者单个方法内部定义了大量局部变量
- 用于存放类的定义Class文件和常量池等
- 项目中类过多
解决方案
- 因为jdbc默认会把查询结果集全部返回到客户端导致oom错误
- 返回的数据量的大小大于了JVM分区中内存空间的大小
本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。