1.现象描述

  (1)使用 Mybatis 在进行数据更新时,大部分时候update语句都需要通过动态SQL进行拼接。在其中,if标签中经常会有 xxx !='' 这种判断,若 number 类型的字段上传递的值为 0, 执行更新时会发现数据库中的数据并没有被更新成 0,这种异常现象不会报错,所以容易被忽视。

    <update id="update" parameterType="com.hrh.mybatis.bean.Person">
update tab_person
<set>
<if test="id != null">
id = #{id,jdbcType=BIGINT},
</if>
<if test="name != null">
name= #{name,jdbcType=VARCHAR},
</if>
<if test="age != null and age !=''" >
age= #{age,jdbcType=BIGINT}
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>

  (2)在 if 标签中有时会用到加条件的判断,如 xxx != ‘x’,如果筛选条件中只有单个字符时,这样拼接执行会报错 

  ### Error querying database. Cause: java.lang.NumberFormatException: For input string: "张三"
  ### Cause: java.lang.NumberFormatException: For input string: "张三"

    <select id="selectByCondition" resultType="com.hrh.mybatis.bean.Person" parameterType="java.lang.String">
select
<include refid="Base_Column_List"/>
from tab_person
where
<if test="name != null and name !='a'">
name = #{name,jdbcType=VARCHAR}
</if>
</select>

  2.原因探究

  (1)Mybatis的表达式使用 OGNL 处理的,若对象是一个 number 类型,值为0时将被解析为 false,否则为 true,浮点型 0.00也是如此。所以问题1中的 <if test="age != null and age !=''" >当age为0时导致表达式的值为false,不进行SQL拼接,执行更新后数据库中的数据不会被更新成0。

  所以对于insert语句拼接也是一样的,<if test="age != null and age !=''" >当age为0时导致表达式的值为false,不进行SQL拼接,导致参数和值传递不一致报错

  ### Error updating database. Cause: java.sql.SQLException: Column count doesn't match value count at row 1
  ### The error may involve com.hrh.mybatis.mapper.PersonMapper.insertSelective-Inline
  ### The error occurred while setting parameters
  ### SQL: insert into tab_person ( id, name, age ) values ( ?, ? )
  ### Cause: java.sql.SQLException: Column count doesn't match value count at row 1
   bad SQL grammar []; nested exception is java.sql.SQLException: Column count doesn't match value count at row 1

    <insert id="insertSelective" parameterType="com.hrh.mybatis.bean.Person">
insert into tab_person
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null">
id,
</if>
<if
test="name != null">
name,
</if>
<if test="age != null">
age
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null">#{id,jdbcType=BIGINT},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="age != null and age !=''">
#{age,jdbcType=BIGINT}
</if>
</trim>
</insert>

  (2)单引号 '' 内如果为单个字符时,OGNL 将会识别为Java的char 类型,String类型与char 类型做运算时会报错。

  3.解决办法

  (1)number 类型的字段在进行拼接时只需要判断 xxx!=null即可。

    <update id="update" parameterType="com.hrh.mybatis.bean.Person">
update tab_person
<set>
<if test="id != null">
id = #{id,jdbcType=BIGINT},
</if>
<if test="name != null">
name= #{name,jdbcType=VARCHAR},
</if>
<if test="age != null" >
age= #{age,jdbcType=BIGINT}
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>

  (2)第二种情况只需要将单引号和双引号调换即可。

    <select id="selectByCondition" resultType="com.hrh.mybatis.bean.Person" parameterType="java.lang.String">
select
<include refid="Base_Column_List"/>
from tab_person
where
<if test='name != null and name !="a"'>
name = #{name,jdbcType=VARCHAR}
</if>
</select>

自己挖的坑自己填--Mybatis mapper文件if标签中number类型及String类型的坑的更多相关文章

  1. MyBatis mapper文件中的变量引用方式#{}与${}的差别

    MyBatis mapper文件中的变量引用方式#{}与${}的差别 #{},和 ${}传参的区别如下:使用#传入参数是,sql语句解析是会加上"",当成字符串来解析,这样相比于$ ...

  2. [DB][mybatis]MyBatis mapper文件引用变量#{}与${}差异

    MyBatis mapper文件引用变量#{}与${}差异 默认,使用#{}语法,MyBatis会产生PreparedStatement中.而且安全的设置PreparedStatement參数,这个过 ...

  3. intellij idea 插件开发--快速定位到mybatis mapper文件中的sql

    intellij idea 提供了openApi,通过openApi我们可以自己开发插件,提高工作效率.这边直接贴个链接,可以搭个入门的demo:http://www.jianshu.com/p/24 ...

  4. mybatis mapper文件sql语句传入hashmap参数

    1.怎样在mybatis mapper文件sql语句传入hashmap参数? 答:直接这样写map就可以 <select id="selectTeacher" paramet ...

  5. ][mybatis]MyBatis mapper文件中的变量引用方式#{}与${}的差别

    转自https://blog.csdn.net/szwangdf/article/details/26714603 MyBatis mapper文件中的变量引用方式#{}与${}的差别 默认情况下,使 ...

  6. MyBatis mapper文件中使用常量

    MyBatis mapper文件中使用常量 Java 开发中会经常写一些静态常量和静态方法,但是我们在写sql语句的时候会经常用到判断是否等于 //静态类 public class CommonCod ...

  7. Mybatis mapper文件占位符设置默认值

    如果要设置占位符默认值的话:需要进行 设置 org.apache.ibatis.parsing.PropertyParser.enable-default-value 属性为true启用占位符默认值处 ...

  8. [转载]MyBatis mapper文件中的变量引用方式#{}与${}的差别

    转载自:http://blog.csdn.net/szwangdf/article/details/26714603 默认情况下,使用#{}语法,MyBatis会产生PreparedStatement ...

  9. Mybatis Mapper文件中的一小坑

    前几天来一需求,实现过程中需要修改一个底层的查询接口,具体修改就是在where中添加一个条件,由于这个底层SQL使用的地方太多,所以就想着是用if加一标识符做个判断,传一个只有我会使用的参数,然后动态 ...

随机推荐

  1. Kubernets二进制安装(13)之部署Flannel

    Flannel简介 ​ Flannel是CoreDNS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址 ...

  2. windows cmd 查看远程连接端口

    查看远程端口号 Cmd tasklist  /svc 在输出的内容中查找svchost.exe进程下termservice服务对应的PID,在此查看的PID为:276 然后输入命令:netstat   ...

  3. codeforces 1016C - Vasya And The Mushrooms 【构造 + 思维】

    题目链接:戳这里 题意:从(1,1)出发,一遍把格子走完,每个格子只能走一次.问怎么走总和最大. 解题思路:画图可知,总共就3种走法的混合. dw: 样例1的走法 up: 样例1反过来的走法 lp: ...

  4. 智能社讲解js基础

    一,Javascript的组成ECMAScript:翻译,核心,解释器,DOM:文档对象模型,Document Object Model 操作HTML的能力,document对象BOM:浏览器对象模型 ...

  5. Leetcode(32)-最长有效括号

    给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 示例 1: 输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()&quo ...

  6. 手工数据结构系列-C语言模拟队列 hdu1276

    #include <stdio.h> #include <stdlib.h> #define init_size 1000 typedef struct { int head, ...

  7. 『数据结构与算法』二叉查找树(BST)

    微信搜索:码农StayUp 主页地址:https://gozhuyinglong.github.io 源码分享:https://github.com/gozhuyinglong/blog-demos ...

  8. Python对excel的基本操作

    Python对excel的基本操作 目录 1. 前言 2. 实验环境 3. 基本操作 3.1 安装openpyxl第三方库 3.2 新建工作簿 3.2.1 新创建工作簿 3.2.2 缺省工作表 3.2 ...

  9. C++ Primer笔记

    C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...

  10. CSS 检测 IE 浏览器

    CSS 检测 IE 浏览器 <!--[if IE]> <link href="ie.css" rel="stylesheet"> < ...