码周记(第五期)

提示:可能对很多人来说码周记中的内容比较菜,不喜勿喷!!!

简介

本周想分享以下几个内容:

  1. NestedServletException中的java.lang.reflect.UndeclaredThrowableException
  2. 你不知道的mybatis单值传参问题
  3. Navicat 导出excel后数字显示科学计数法问题
  4. mysql排序分页问题

一、NestedServletException

我相信对于很多人初学者来说甚至都没有见过这个异常,这个东西是springMV中web.util下面的。

据我所知:

如果有异常没有在controller层处理掉的话,就会被springmvc的这个异常捕获处理,然后前端就会出现一个很长的异常(这个个人觉得还可以接受),比如:Request processing failed; nested exception is java.lang.ArithmeticException: / by zero…

如果我们在项目中用到了aop,然后这个controller又收到了aop的管理,那么这个在controller中没有捕获处理的异常会先被aop捕获,然后这个时候问题就出现了!!!

后端访问层次差不多就是这样:
码周记(第五期)_第1张图片

aop中:

 try {
    //执行controller
    result = point.proceed();
    return result;
 } catch (Throwable e) {
    //抛出自定义的异常
 }

filter中:

  try {
      //过滤
      chain.doFilter(request, resp);
   } catch (Exception e) {
       // 返回json
        response.setContentType("text/json; charset=utf-8");
        PrintWriter pw = resp.getWriter();
        pw.write(ResponseUtils.getFailResponseStr( e.getMessage()));
        if (pw != null) {
            pw.close();
        }
        return;
   }

问题1:我在controller中没有处理的异常会到aop中被捕获进入catch (Throwable e),然后抛出一个自定义的异常,在外层的filter中被捕获进入 catch (Exception e) ,然后输出一下e.getMessage()。理论上是不是这样走一点问题都没有,但是实际上,返回给前端的是:java.lang.reflect.UndeclaredThrowableException

问题2:我在aop中抛出的异常会被捕获进入catch (Throwable e),然后抛出一个自定义的异常,在外层的filter中被捕获进入 catch (Exception e) ,然后输出一下e.getMessage()。理论上是不是这样走也没问题,但是实际上,返回给前端的又是:java.lang.reflect.UndeclaredThrowableException

个人觉得以上两种情况是不能接受的,前端完全不知道什么鬼,到底什么错都不清楚。。。

分析:aop中捕获的异常抛出去,其实并不是直接到filter,我猜测,我们在aop中抛出去的异常应该是被java动态代理处理异常的一个东西拦截了,据网上所说(可能不对,我没仔细研究过),一个异常是检查型异常并且没有在动态代理的借口处声明,那么它将会被包装成java.lang.reflect.UndeclaredThrowableException,之后应该是被springmvc中的NestedServletException捕获了,这个时候我们看到的异常就已经是java.lang.reflect.UndeclaredThrowableException了
码周记(第五期)_第2张图片
解决:其实解决方法很简答,我们只要debug一下看看他有多少层,然后对应的去获取message就行了!
码周记(第五期)_第3张图片

在拦截器中的catch里面加上这个代码即可:

        String msg = null;
        //如果是NestedServletException异常或者是他的子异常
        if (e instanceof NestedServletException){
            //获取内部异常
            e = (Exception)  ((NestedServletException) e).getRootCause();
            if (e != null){
                msg = e.getCause().getMessage();
            }
        } else {
            msg = e.getMessage();
        }

二、mybatis单值传参问题

大部分人看到这个标签是不是会有疑问,不是应该是mybatis多值传参问题吗?不!单值传参也有你想不到的问题!

如果是多值传参,如果不使用@Param这个注解,在xml中直接用参数名字,很明显就会报错,但是如果单值传参不加这个注解也会报错:There is no getter for property named XXX 怎么说?你是不是很震惊!?

据我所知,好像是单值传参的情况下,如果在xml中有对这个参数做判断的话:

  
     and AAA=#{XXX}
 

这个单值传参如果没有加注解就会报错,广大的mybatis使用者,可以去试一下!!!

三、Navicat 导出excel后数字显示科学计数法问题

码周记(第五期)_第4张图片
解决:在sql查询中拼接一下\t即可

CONCAT(pd.order_sn,'\t') as 订单号 

四、mysql排序分页问题

这个问题本来早在前几期就想发出来的,但是一直没有研究明白。。。这个可以说是mysql的一个bug,也可以说是我经历的太少!

问题:查询一个结果集(根据某个字段降序),一条记录在不加limit的时候出现在92行,然后在sql之后加了一个limit 90,10之后,这条记录不见了?难道limit 90,10不是取第90~99条记录吗???

分析:个人猜想应该是order by之后的几个字段存在相同值太多,然后mysql也不知道到底要取那一条,如果刚好卡在分页的哪一环节,有可能一条记录会出现好几次,也可能会有记录查询不出来;

网上分析(个人觉得还行): https://www.cnblogs.com/glon/p/6806064.html

MySQL 使用 limit 进行分页时,如果排序字段有相同值的情况下,由于排序字段数据重复,可能会导致每次查询排序后结果顺序不同,分页还是会出现重复数据。

解决:

1、使用子查询:先不使用limit,先order by,然后在查出来的结果中使用limit - - - 个人觉得有点蠢。。。

2、再加一个排序字段,提高排序的唯一性,最好保证排序的字段在表中的值是唯一的,即id这种字段

你可能感兴趣的:(码周记)