MySQL+MyBatis下批量修改数据的问题

6 篇文章 0 订阅

今天处理数据批量的更新,场景是这样子的,web站管理的字典功能,需要添加一个记录的整体描述,以及详细内容的描述。一个字典整体概述只有一组信息,但是其详细内容,会有很多项,不确定。
这个场景,在关系型数据库操作中,就是典型的1vN的问题,即一对多的问题。
做内容修改时,涉及到批量的更新过程。这里,只针对具体的问题描述细节,不过多介绍字典的设计。
字典的查询没有问题,mybatis的mapper函数如下:

<resultMap id="FullConfResultMap" type="com.tg.ecs.system.model.SysConfElement" >
    <!--   
              注意,这种基于has-one,以及has-many的模式,会造成结果映射出错。个人理解,这种复合查询中,顶层元素中
              必须有基本数据类型的成员,否则会出现结果个数映射转换失败。
    <association property="scc" javaType="com.tg.ecs.system.model.SysConfCategory">
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="code_name" property="codeName" jdbcType="VARCHAR" />
        <result column="info_name" property="infoName" jdbcType="VARCHAR" />
        <result column="remark" property="remark" jdbcType="VARCHAR" />
        <result column="who_cm" property="whoCm" jdbcType="INTEGER" />
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
        <result column="in_use" property="inUse" jdbcType="BIT" />
    </association>
    -->
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="code_name" property="codeName" jdbcType="VARCHAR" />
    <result column="info_name" property="infoName" jdbcType="VARCHAR" />
    <result column="c_remark" property="remark" jdbcType="VARCHAR" />
    <result column="who_cm" property="whoCm" jdbcType="INTEGER" />
    <result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
    <result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
    <result column="in_use" property="inUse" jdbcType="BIT" />
    <collection property="scds" ofType="com.tg.ecs.system.model.SysConfDetail">
        <result column="did" property="id" jdbcType="INTEGER" />
        <result column="code" property="code" jdbcType="VARCHAR" />
        <result column="info" property="info" jdbcType="VARCHAR" />
        <result column="d_remark" property="remark" jdbcType="VARCHAR" />
        <result column="category_id" property="categoryId" jdbcType="INTEGER" />
    </collection>
  </resultMap>
  <select id="selectOneFullConf" resultMap="FullConfResultMap">
      select tscc.id, tscc.code_name, tscc.info_name, 
             tscc.remark as c_remark,
             tscc.who_cm, tscc.create_time, tscc.update_time, tscc.in_use,
             tscd.id as did, 
             tscd.code, tscd.info, 
           tscd.remark as d_remark, 
           tscd.category_id 
         from sys_conf_category tscc, sys_conf_detail tscd
      where tscd.category_id = tscc.id 
         and tscc.id = #{cid, jdbcType=INTEGER}
  </select>

这里,我的SysConfDetail的POJO代码如下:

public class SysConfDetail {
    
    private Integer id;
    
    private String code;

    private String info;

    private String remark;

    private Integer categoryId;
   
    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info == null ? null : info.trim();
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark == null ? null : remark.trim();
    }

    public Integer getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(Integer categoryId) {
        this.categoryId = categoryId;
    }

    /**
     * @return the code
     */
    public String getCode() {
        return code;
    }

    /**
     * @param code the code to set
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @return the id
     */
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }
}

就是查询中collection的数据类型。

我的设计中,字典的操作是下面这个样子的,请看下图
在这里插入图片描述
当我更新上图中的内容后,点击保存,我的WEB应用后台总是爆出一个很奇怪的问题:
分析了错误日志,开始总是不知道什么原因,以为是其中的info字段乱码。分析自己的update的SQL语句:

<update id="updateOneConfDetail" parameterType="java.util.List">
    <!-- 注意这里,index以及open,close没有用,所以就不做配置了,默认的 -->
      <foreach collection="scds" item="ocd" separator=";">  
        UPDATE sys_conf_detail
        <set>  
           code = #{ocd.code},  
           info = #{ocd.info},  
           remark = #{ocd.remark}
        </set>  
        <where>  
           id = #{ocd.id, jdbcType=INTEGER} and category_id = #{ocd.categoryId, jdbcType=INTEGER}  
        </where>  
      </foreach>                
  </update>

上面的SQL语句,红色部分separator=“;”,是重点。 回想到官方的描述,关于一行SQL语句中执行多个子SQL的时候(比如这里,MySQL默认是用分号最为一个语句的结束),会出问题。请参考MySQL官方文档描述

allowMultiQueries

Allow the use of ';' to delimit multiple queries during one statement (true/false), defaults to 'false', and does not affect the addBatch() and executeBatch() methods, which instead rely on rewriteBatchStatements.

Default: false

Since version: 3.1.1

这个是问题的关键,我们可以在jdbc的地址url中添加一下这个allowMultiQueries=true的参

jdbc.url=jdbc\:mysql\://10.90.7.2\:3306/rdcenter?useUnicode\=true&characterEncoding\=UTF-8&zeroDateTimeBehavior\=convertToNull&allowMultiQueries\=true

修改后,再次启动我的应用,就不再报上述的exception问题了。

总结:

mysql数据库,要在一个statement中执行多条sql子句的时候,需要打开这个功能,默认该功能是关闭的,也就是在url地址栏开启allowMultiQueries=true.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值