前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mybatis-plus使用上需要注意的问题

mybatis-plus使用上需要注意的问题

作者头像
路行的亚洲
发布2021-08-20 15:05:04
2.6K0
发布2021-08-20 15:05:04
举报
文章被收录于专栏:后端技术学习后端技术学习

mybatis-plus使用上需要注意的问题

1.问题产生

之前,开发项目使用的是tk-mapper,当使用批量操作时,通常使用insertList就可以了。但是,最近的项目使用的是mybaits-plus,在使用批量操作saveBatch的使用,却遇到了一个问题,这个一开始让我以为我的数据出现了重复,但是仔细看,不是数据出现了重复,而是因为有一个字段相同,报唯一索引字段重复插入 Duplicate entry。

下面是我插入数据的sql和相对应的数据信息:

但是插入却报了错:

第一个感觉很诧异,批量插入操作,为啥还报了唯一索引异常了呢。

2.查看mybatis-plus封装代码

可以看到其批量操作的本质是一个for循环操作,注意参数里面出现了ignore:

代码语言:javascript
复制
/**
 * 批量插入
 *
 * @param entityList ignore
 * @param batchSize  ignore
 * @return ignore
 */
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveBatch(Collection<T> entityList, int batchSize) {
    String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
    int size = entityList.size();
    executeBatch(sqlSession -> {
        int i = 1;
        //遍历需要插入的数据列表,也即将数据想打包,然后执行批量操作
        for (T entity : entityList) {
            sqlSession.insert(sqlStatement, entity);
            if ((i % batchSize == 0) || i == size) {
                sqlSession.flushStatements();
            }
            i++;
        }
    });
    return true;
}

同时还可以看到其插入操作底层却是更新操作。

代码语言:javascript
复制
@Override
public int insert(String statement, Object parameter) {
  return update(statement, parameter);
}

可以看到mybatis的执行器执行的是更新方法:

代码语言:javascript
复制
@Override
public int update(String statement, Object parameter) {
  try {
    dirty = true;
    MappedStatement ms = configuration.getMappedStatement(statement);
    return executor.update(ms, wrapCollection(parameter));
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}

而当插入数据完成后,刷新语句,然后执行批量操作

代码语言:javascript
复制
  /**
     * 执行批量操作
     *
     * @param fun fun
     * @since 3.3.0
     */
    protected void executeBatch(Consumer<SqlSession> fun) {
        Class<T> tClass = currentModelClass();
        SqlHelper.clearCache(tClass);
        SqlSessionFactory sqlSessionFactory = SqlHelper.sqlSessionFactory(tClass);
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            fun.accept(sqlSession);
            sqlSession.commit();
        } catch (Throwable t) {
            sqlSession.rollback();
            Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
            if (unwrapped instanceof RuntimeException) {
                MyBatisExceptionTranslator myBatisExceptionTranslator
                    = new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
                throw Objects.requireNonNull(myBatisExceptionTranslator.translateExceptionIfPossible((RuntimeException) unwrapped));
            }
            throw ExceptionUtils.mpe(unwrapped);
        } finally {
            sqlSession.close();
        }
    }
}

3.出现异常的地方

我的执行操作却走到了catch中:

也即在执行刷新操作就出现了错误。可以看到入参中是有数据的:

问题出现在刷新语句上。

4.问题的解决

在网上查到能够解决这个问题的两种方法:一种是在mysql的数据源中加入allowMultiQueries=true,还有一种结果在sql中使用igrone,我试了一下在其后加上allowMultiQueries=true,发现可以实现。

那为了解决mybatis-plus的批量插入操作可以使用ignore来避免批量插入失败的问题。

经过代码排查,以及批量update语句通过SQL工具直接执行均能成功,排除代码和sql语句问题,发现使用mybatis进行批量插入与更新时,必须在配置连接url时指定allowMultiQueries=true

但是发现我们的配置数据库配置中居然没有加:allowMultiQueries=true

代码语言:javascript
复制
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai&allowMultiQueries=true

同时在网上还看到:

从 MyBatis3.3.1 版本开始,MyBatis开始支持批量新增回写主键值的功能,这个功能首先要求数据库主键值为自增类型,同时还要求该数据库提供的 JDBC 驱动可以支持返回批量插入的主键值(JDBC提供了接口,但并不是所有数据库都完美实现了该接口),因此到目前为止,可以完美支持该功能的仅有MySQL数据库。由于SQL Server数据库官方提供的 JDBC 只能返回最后一个插入数据的主键值,所以不能支持该功能。mybatis-plus的作者说可以使用 mp idWroker 完美解决。

同时在查资料的时候,发现低版本的mybatis-plus会出现批量更新insertBatch失败的问题。如果使用低版本出现这个问题,那更换成高版本的可以解决这个问题。

如果还不行的话,尝试在mybatis的xml文件中,使用sql的时候加上igrone.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • mybatis-plus使用上需要注意的问题
    • 1.问题产生
      • 2.查看mybatis-plus封装代码
        • 3.出现异常的地方
          • 4.问题的解决
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档