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

  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)第二种情况有多种解决办法:

  I.需要将单引号和双引号调换即可。

    <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>

   II.添加toString() 进行类型转换

    <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'.toString()">
            name = #{name,jdbcType=VARCHAR}
        </if>
    </select>

   III.添加转义实体字符串引号

    <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 != &quot;a&quot;">
            name = #{name,jdbcType=VARCHAR}
        </if>
    </select>
您可以使用Mybatis-Plus的BatchInsert功能来批量插入数据,具体步骤如下: (1)首先创建一个实体类,包含需要插入的属性(name,number,id)。 (2)创建一个Mapper,并继承Mybatis-Plus提供的BaseMapper。 (3)在Mapper中使用@InsertProvider注解,并指定插入数据的Provider类: @InsertProvider(type = BatchInsertProvider.class, method = "dynamicSQL") (4)在Provider类中实现批量插入的SQL语句,如下所示: public class BatchInsertProvider { public String batchInsert(Map map) { List dataList = (List) map.get("list"); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("insert into table_name (name,number,id) values "); for (Object data : dataList) { Map dataMap = (Map) data; stringBuilder.append("("); stringBuilder.append("'").append(dataMap.get("name")).append("',"); stringBuilder.append("'").append(dataMap.get("number")).append("',"); stringBuilder.append("'").append(dataMap.get("id")).append("'"); stringBuilder.append("),"); } stringBuilder.deleteCharAt(stringBuilder.length() - 1); return stringBuilder.toString(); } } (5)在Service中调用Mapper的批量插入方法,如下所示: @Autowired private Mapper mapper; public boolean batchInsert(List dataList) { Map map = new HashMap<>(); map.put("list", dataList); int result = mapper.batchInsert(map); return result == dataList.size(); } 以上就是使用Mybatis-Plus实现批量插入的步骤,希望能够对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值