Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException——Mybatis批量处理错误处理

2 篇文章 0 订阅
0 篇文章 0 订阅

在进行批量处理的时候,在后台发现报错,日志部分如下:

bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Syntax error:

出现了badSQlgrammar错误,在(某一个表中)出现了delete错误。
由于在批量操作的时候,我们是通过生成多条SQL语句,然后进行拼接,再用Mybatis进行处理,但是遇到了问题。

<update id="setWeiboEmotionByList" parameterType="java.util.List">
        <foreach collection="list" item="item" open="" close="" separator=";">
            UPDATE weibo_content
            SET
                EMOTION = #{item.emotion}
            WHERE
                WEIBO_ID = #{item.weibo_id}
        </foreach>
    </update>

类似上面的操作方式,使用foreach来对list中的语句进行拼接和遍历最后多条SQL语句进行执行
在这里插入图片描述
由上图所示,但是却触发了JDBC4 的MySQLSyntaxErrorException,经过资料查询,观察MySQLSyntaxErrorException实例:

public void create(Project project) throws IllegalArgumentException, DAOException {
	if (project.getProjectId() != 0) {
		throw new IllegalArgumentException("Project is already created, the project ID is not null.");
	}

	Object[] values = { project.getProjectNumber(), project.getProjectName(), 
			project.getActivity(), project.getPerNumber(),
			toSqlDate(project.getDate()), project.getTime()}; 
		
	try (Connection connection = daoFactory.getConnection();
		PreparedStatement statement = prepareStatement(connection, 
			SQL_INSERT_PROJECT, true, values);) {
		int affectedRows = statement.executeUpdate();
		if (affectedRows == 0) {
			throw new DAOException("Creating user failed, no rows affected.");
		}
		try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
			if (generatedKeys.next()) {
				project.setProjectId(generatedKeys.getLong(1));
			} else {
				throw new DAOException("Creating user failed, no generated key obtained.");
			}
		}
	} catch (SQLException e) {
		throw new DAOException(e);
	}
}

可以看到,出错原因有大概如下原因:

  • 1、其中SQL语句有的出错导致。
  • 2、Mybatis中字段部分与SQl关键字冲突。
  • 3、由于是多条执行(delete xxx……;delete xxx……; delete xxx……;),可能Mybatis不能支持这种批量方式。
  • 4、对于参数传值的时候,使用"#{}“和使用”${}"传值时,会出现不同的问题。**
对这四种错误进行排查:
  • 通过在Navicat中执行每条SQL,发现并无报错,应该不是SQL语句有问题。
  • 在其他单条SQL语句处理和批量查找、批量更新都发现没有此问题。
  • Mybatis是默认不支持这种操作的,但是我们可以通过在mysql配置链接里加上allowMultiQueries参数并置为true。但是还是报同样的错误(也可能和服务器端的配置有关,需要进一步查看)。
  • 很明显全部使用的"#{}",当使用$时是默认无防注入的。其中#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
    表 示 拼 接 s q l 串 , 通 过 {}表示拼接sql串,通过 sql{}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,$ {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,$ {}括号中只能是value。
究其原因(一般原因):

经过查找资料,发现大多数问题都是处在第三条上——对与adllowMultiQueries参数没有置为true,
但是,我们使用的是OceanBase的数据库,虽然理论上支持MySQL中的所有语句,但是在解决问题的两天后,我在阿里巴巴官方文档中看到了:

在这里插入图片描述
确实,这个问题解决了,但是下一个问题出现了:如何换一种方案呢

经过大佬们的商议,决定根据偏移量来进行Mybatis分段的批量操作,

后面继续谈。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值