总结在工作中遇到的有意思的问题,和对应解决方案。遇到一个记录一个。 业务大了,经常会出现莫名其妙的问题。比如好好的插件,莫名其妙不起作用了。这时候不可以改业务代码,或者修改一点点,还得解决问题。
一、Mybatis爬坑
1. mybatis-plus 自动填充失效、分页插件不向下传递拦截链
问题如标题所示,mybatis自动填充不生效,使用分页插件发现这个插件没有向下传递拦截链。
解决方案
- 选择使用Mybatis-plus的分页插件,满足向下传递拦截链的要求。
- 仿造MyBatis-plus的自动填充使用,自定义自动填充插件。解决Mybatis-plus自动填充时而有效时而失效的情况。
2. 使用Spring AOP监控mapper执行时间
公司让优化报表的查询(一个查询据说将近20s,一个接口15秒会超时,所以最坏也得让查询在15s以内),这些报表数据量大,IO非常多,一个查询涉及到几十条sql和IO
因此想要优化,就得知道哪些操作比较费时间,直接用AOP是好的选择,精确打印每一个IO的时间,进行优化
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@Aspect
@Slf4j
public class MapperExecutionTimeAspect {
@Pointcut("execution(* cn.xxx.mapper.*.*(..))")
public void pointcut() {
}
@Around("pointcut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.nanoTime();
Object obj = pjp.proceed();
long end = System.nanoTime();
log.info("调用Mapper方法:执行耗时:{}纳秒,耗时:{}毫秒,{},参数:{}",
(end - begin), (end - begin) / 1000000,
pjp.getSignature().toString(), Arrays.toString(pjp.getArgs()));
return obj;
}
}
二、查询优化
1. 大量mapper IO优化
当查询大报表,并且sql没有太大优化空间的情况下,该如何提升效率呢?
- 也就是说现在IO太多,但是也没办法,业务确实需要这么多的IO
- 单个IO的效率优化,已经没有太多优化空间了,也就是优化sql的方案不可取
- 那么问题就是如何让这些IO能快一点
一般这种情况,就可以考虑多线程了,而且大的报表一般是不用考虑高并发的。所以直接将内容都写到方法中,不定义到类中,就没有线程安全问题。因为没有高并发,也不用考虑栈溢出的问题(每个线程执行都会有一个,线程私有,生命周期与线程相同,是Java方法执行的线程内存模型,每个方法被执行时,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息)
|