Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 448|回复: 0

springboot mybatis常见异常及处理方法

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-13 10:44:29 | 显示全部楼层 |阅读模式

    1.in导致的异常

     Data truncation: Truncated incorrect DOUBLE value:

    异常过程:

    mapper接口如下:

    public int updateBatchId(@Param("batchId")String batchId,@Param("idStr")String idStr);

    xml中sql如下:

        <update id="updateBatchId" parameterType="java.lang.String">
            update pdm_description_error_msg set batch_id = #{batchId},status = "1",process_num = process_num +1
            where id in (#{idStr})
        </update>

    原因分析:

    mybatis中in不能这样写,需要使用foreach,不然就会报如上的错误。

    解决办法:(这里的idStr是以逗号分隔的,形式是这样的:1,2,3,4)

        <update id="updateBatchId" parameterType="java.lang.String">
            update pdm_description_error_msg set batch_id = #{batchId},status = "1",process_num = process_num +1
            where id in
            <foreach item="item" index="index" collection="idStr.split(',')" open="(" separator="," close=")">
                '${item}'
            </foreach>
        </update>

    异常总结

    之前写sql时是使用注解的方式写的,通过那种方式,在java代码中是可以直接使用以逗号分隔的字符串的,例子如下:

        public String updateBatchId(String batchId,String idStr){
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("update pdm_error_msg set batch_id = '" + batchId + "',status=1,process_num=process_num+1 where " +
                    " (status=0 or status = 3) and id in ("+idStr+")");
            return stringBuilder.toString();
        }

    这个是在java中直接拼接的sql可以,可以直接使用带逗号的字符串,在xml不行。

     

    2.group_concat

    这个mysql中关键字其实一般是不会使用的,但是有时使用group by做分组的时候,又希望把分组的结果拿出来,就可能会使用这个关键字,但是,重点是这个但是,如果返回的字段的长度过长,就会直接截断,然后也不抛异常,然后返回出来的结果就是一个阶段后的结果。

    为啥要截断呢?

    mysql为了优化性能

    那多长会截断呢?

    默认就是1024个字节,这才多长啊。

    能不能避免不被截断?

    可以,不过需要mysql的权限,让dba设置,不过dba爸爸估计不会帮这个忙

    总结

    严格来说这个锅不是mybatis的锅,其实是mysql为了优化性能搞的,举个例子,如果你程序开发测试环境随便造的数据,都很短,没问题,当部署到生产环境,运行一段时间,出问题,那估计问题就很严重。

     3.is not null 和 !=    ;    is null 和 =

    这个在平时写sql的时候一般没什么问题,遇见null值判断,都会使用is,或者is not,但是偶尔会写成!=,这就搞飞机了,写成这样sql也不会抛异常,但是就是统计的数据不准确。原因就是null值不能使用 =,!=,<>等判断。

    4.provider中sql语句把反斜线去掉,导致的转义问题 

      更新于--------------------------------------2020-01-15---------------------------------------

      springboot中使用mybatis,现在很多小伙伴都不使用xml的方式写sql了,而是通过provider,如果牵涉到批量操作,基本上大家都不会直接在mapper中写sql,而是在provider中通过字符串拼接的方式来实现sql,这个写一般的sql没什么问题,一旦遇见一些坑爹的场景其实还是xml的方式比较好,比如下面说的问题:

      场景:把表A中的message字段批量读出来,一次读取100条,批量插入到表B,实现方式是在provider中实现字符串拼接

    代码如下:

    public String insertCheckMsgBatch(List<CheckMsg> msgList) {
            StringBuffer sql = new StringBuffer();
            sql.append("insert into table(message,status) values ");
            
            if(!CollectionUtils.isEmpty(msgList)) {
                int i = 0;
                for(CheckMsg msg : msgList) {
                    i++;
                    sql.append("("+msg.getMessage()+","+msg.getStatus());
                    
                    if(i < msgList.size()) {
                        sql.append("),");
                    } else {
                        sql.append(")");
                    }
                }
            }
            
            return sql.toString();
        }

    出现的问题: 由于表A中的message带有转义字符,会把字符串中的单引号和双引号转义,但是被上面一搞,所有的转义字符都没了,比如  "\"abc\'"  经过这玩意一搞变成了  ""abc'",但是这个也可以正常插入数据库,但是下次读出来就会出问题,因为这是一个异常的字符串。

    解决办法:

      上面问题的根源在于通过provider没有经过PreparedStatement预编译,如果经过这个预编译mybatis其实是可以处理这些特殊的字符的,ok,那就想办法让mybatis预编译,有两种方法,一种是改成xml方式,这种还要改,麻烦,另一个种是直接通过在mapper文件中写批处理sql的方式,这种实际和在xml一样。如下:

      

     @Insert({"<script>" +
                "insert into table(message,status) values " +
                "<foreach item='item' index='index' collection='msgList' separator=','> " +
                "(#{item.message},#{item.status})" +
                "</foreach>" +
                "</script>"})
        public int insertMsgBatch(@Param("msgList") List<Msg> msgList);

    这样就可以解决问题了,记录一下

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-20 09:36 , Processed in 0.066526 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表