今天处理数据批量的更新,场景是这样子的,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应用后台总是爆出一个很奇怪的问题:

org.springframework.jdbc.BadSqlGrammarException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE sys_conf_detail
SET code = '',
info = '产�详' at line
### The error may involve com.tg.ecs.system.dao.SysConfDetailMapper.updateOneConfDetail-Inline
### The error occurred while setting parameters
### SQL: UPDATE sys_conf_detail SET code = ?, info = ?, remark = ? WHERE id = ? and category_id = ? ; UPDATE sys_conf_detail SET code = ?, info = ?, remark = ? WHERE id = ? and category_id = ? ; UPDATE sys_conf_detail SET code = ?, info = ?, remark = ? WHERE id = ? and category_id = ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE sys_conf_detail
SET code = '',
info = '产�详' at line
; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE sys_conf_detail
SET code = '',
info = '产�详' at line
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:)
at com.sun.proxy.$Proxy11.update(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:)
at com.sun.proxy.$Proxy42.updateOneConfDetail(Unknown Source)
at com.tg.ecs.system.service.impl.SysConfDetailService.updateOneConfDetail(SysConfDetailService.java:)
at com.tg.ecs.system.service.impl.SysConfDetailService$$FastClassBySpringCGLIB$$373671b0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
at org.springframework.transaction.interceptor.TransactionInterceptor$.proceedWithInvocation(TransactionInterceptor.java:)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:)
at com.tg.ecs.system.service.impl.SysConfDetailService$$EnhancerBySpringCGLIB$$f6432ee7.updateOneConfDetail(<generated>)
at com.tg.ecs.system.service.impl.SysConfDetailService$$FastClassBySpringCGLIB$$373671b0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
at org.springframework.transaction.interceptor.TransactionInterceptor$.proceedWithInvocation(TransactionInterceptor.java:)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:)
at com.tg.ecs.system.service.impl.SysConfDetailService$$EnhancerBySpringCGLIB$$b9909d6d.updateOneConfDetail(<generated>)
at com.tg.ecs.system.controller.ConfController.saveCategory(ConfController.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
at java.lang.reflect.Method.invoke(Method.java:)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$.invoke(ResourceMethodInvocationHandlerFactory.java:)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$.run(AbstractJavaResourceMethodDispatcher.java:)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:)
at org.glassfish.jersey.server.ServerRuntime$.run(ServerRuntime.java:)
at org.glassfish.jersey.internal.Errors$.call(Errors.java:)
at org.glassfish.jersey.internal.Errors$.call(Errors.java:)
at org.glassfish.jersey.internal.Errors.process(Errors.java:)
at org.glassfish.jersey.internal.Errors.process(Errors.java:)
at org.glassfish.jersey.internal.Errors.process(Errors.java:)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:)
at org.glassfish.jersey.servlet.ServletContainer.serviceImpl(ServletContainer.java:)
at org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:)
at org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:)
at org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
at com.tg.ecs.core.xss.XssFilter.doFilter(XssFilter.java:)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:)
at org.apache.shiro.web.servlet.AbstractShiroFilter$.call(AbstractShiroFilter.java:)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:)
at java.lang.Thread.run(Thread.java:)

分析上面的错误日志,开始总是不知道什么原因,以为是其中的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.

MySQL+MyBatis下批量修改数据的问题的更多相关文章

  1. python--同一mysql数据库下批量迁移数据

    最近接手些mysql数据库维护,发现mysql在批量操作方面就是个渣渣啊,比起MS SQL SERVER简直就是“不可同日而语”. 咨询了下MySQL的高手,对于数据迁移这种问题,一种处理方式就是直接 ...

  2. mybatis foreach批量插入数据:Oracle与MySQL区别

    mybatis foreach批量插入数据:Oracle与MySQL不同点: 主要不同点在于foreach标签内separator属性的设置问题: separator设置为","分 ...

  3. MYSQL中约束及修改数据表

    MYSQL中约束及修改数据表 28:约束约束保证数据的完整性和一致性约束分为表级约束和列级约束约束类型包括:    NOT NULL(非空约束)    PRIMARY KEY(主键约束)    UNI ...

  4. 批量修改数据sql

    --insert into P_ZPROMOTION_DOC_ITEMS (AKTNR,MATNR,MINGROSS,MCRANK,MCUPRICE,MAXBAKTNR,MAXBPAMONT,MAXB ...

  5. ArcGIS 批量修改数据名称-arcgis案例实习教程

    ArcGIS 批量修改数据名称-arcgis案例实习教程 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 功能:批量修改数据/文件名称 使用方法: 输入:文件夹(或者 ...

  6. Linux下批量修改文件及文件夹所有者及权限

    Linux下批量修改文件及文件夹所有者及权限需要使用到两个命令,chmod以及chown 例:对/opt/Oracle/目录下的所有文件与子目录执行相同的权限变更: chmod -R 700 /opt ...

  7. MySQL(三) —— 约束以及修改数据表

    约束: 1. 约束保证数据的完整性和一致性: 2. 约束分为表级约束和列级约束: 3. 约束类型包括:NOT NULL, PRIMARY KEY, UNIQUE KEY, DEFAULT, FOREI ...

  8. myBatis获取批量插入数据的主键id

    在myBatis中获取刚刚插入的数据的主键id是比较容易的 , 一般来说下面的一句话就可以搞定了 , 网上也有很多相关资料去查. @Options(useGeneratedKeys = true, k ...

  9. mysql开启远程登陆(修改数据表和授权两种方法)

    一.确认防火墙没有阻止3306端口(一般服务器默认会屏蔽掉) windows防火墙例外设置方法 控制面板(右上角选择查看方式为大图标)---防火墙---高级设置---高级设置---出站规则---最右边 ...

随机推荐

  1. Bug01_MyBatis_不允许有匹配 "[xX][mM][lL]" 的处理指令目标。

    xml 文件格式不正确.一般是开头约束不对. 我出现的问题是:<?xml version="1.0" encoding="UTF-8"?>写了两遍, ...

  2. 【Python】socket编程-3

    . SocketServer最简单的使用方法: () 创建一个Handler类,继承自BaseRequestHandler,重写其handle(),在该方法中完成对请求的处理. () 实例化一个Ser ...

  3. JSON的学习,希望可以指导

    1.JSON的介绍 是一种轻量级的数据交换格式.简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言. 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率. 2.格式 JSON ...

  4. 对jQuery ajax的认识

    1.ajax() 方法通过 HTTP 请求加载远程数据. 2.该方法是 jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等.$.ajax() 返回其创建的 XML ...

  5. 【转载】 强化学习(七)时序差分离线控制算法Q-Learning

    原文地址: https://www.cnblogs.com/pinard/p/9669263.html ------------------------------------------------ ...

  6. 强化学习论文(Scalable agent alignment via reward modeling: a research direction)

     原文地址: https://arxiv.org/pdf/1811.07871.pdf ======================================================== ...

  7. MySQL(2)数据库 表的查询操作

    来源参考https://www.cnblogs.com/whgk/p/6149009.html 跟着源博客敲一遍可以加深对数据库的理解,同时对其中一些代码做一些改变,可以验证自己的理解. 本文改动了其 ...

  8. Templates中的for标签

    for 标签 {% for 变量 in 元组|列表|字典 %} {% endfor %} 在 Jinja2 模板的循环中,支持内部变量 - loop loop作用:记载当前循环中的一些相关信息 loo ...

  9. sticky footer 和 flex布局的原理

    Sticky footers设计是最古老和最常见的效果之一,大多数人都曾经经历过.它可以概括如下:如果页面内容不够长的时候,页脚块粘贴在视窗底部:如果内容足够长时,页脚块会被内容向下推送. 一.使用f ...

  10. xdoj 1067组合数学+动态规划 (一个题断断续续想了半年 233)

    题目分析 : (8 4) 可以由(7 4),(6,4),( 4,4) 基础上转化 意味着一个新加入的元素可以按照它加入的方式分类,从而实现动态规划 核心:加入方式 新加入的元素构成转换环的元素个数(n ...