`
234390216
  • 浏览: 10229805 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:462459
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1775244
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1398176
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:394947
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:679877
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:530770
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1183578
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:467457
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:151275
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:68022
社区版块
存档分类
最新评论

Mybatis的Executor介绍(二)——批处理,批量更新

阅读更多

6       MybatisExecutor介绍(二)——批处理

       在程序中,有时候我们需要批量的去操作一些数据,批量的新增、修改、删除,如果是通过for循环一条记录一条记录的去更新无疑效率会比较慢。更佳的做法无疑是采用JDBC对批处理的支持。Mybatis基于JDBC对批处理的支持,也提供了进行数据的批量操作的APIBatchExecutor。下面是一段JDBC进行批量操作的示例代码。

   @Test

   public void testJDBCBatch() throws SQLException {

      String sql = "insert into t_user(name, mobile, email) values(?,?,?)";

      try (Connection conn = dataSource.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql);) {

        List<User> users = this.getUsers();

        for (User user : users) {

           pstmt.setString(1, user.getName());

           pstmt.setString(2, user.getMobile());

           pstmt.setString(3, user.getEmail());

           pstmt.addBatch();

        }

        pstmt.executeBatch();

        conn.commit();

      }

   }

 

       在每一次调用的时候是调用Statement.addBatch()方法,最终所有的参数都传递完了,没有更多的参数时调用Statement.executeBatch()方法进行批量操作。在上一篇博文中我们查看了BatchExecutor的源码,它的核心代码doUpdate()方法,每次被调用的时候都是以handler.batch()结束,而handler.batch()对应的底层代码是调用对应的StatementaddBatch()方法。那它是在什么时候执行executeBatch()呢?

  @Override

  public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {

    final Configuration configuration = ms.getConfiguration();

    final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);

    final BoundSql boundSql = handler.getBoundSql();

    final String sql = boundSql.getSql();

    final Statement stmt;

    if (sql.equals(currentSql) && ms.equals(currentStatement)) {

      intlast = statementList.size() - 1;

      stmt = statementList.get(last);

     handler.parameterize(stmt);//fix Issues 322

      BatchResult batchResult = batchResultList.get(last);

      batchResult.addParameterObject(parameterObject);

    } else {

      Connection connection = getConnection(ms.getStatementLog());

      stmt = handler.prepare(connection);

      handler.parameterize(stmt);    //fix Issues 322

      currentSql = sql;

      currentStatement = ms;

      statementList.add(stmt);

      batchResultList.add(new BatchResult(ms, sql, parameterObject));

    }

  // handler.parameterize(stmt);

    handler.batch(stmt);

    return BATCH_UPDATE_RETURN_VALUE;

  }

 

       它的executeBatch()是在doFlushStatements()方法调用中调用的,它会在当前Executor进行commit时调用,也会在当前Executor第一次执行doQuery()时调用,在这个时候都会调用ExecutorflushStatements()方法,而BaseExecutor在执行flushStatements()时最终会调用其doFlushStatements()方法。当然,我们也可以手动的调用SqlSessionflushStatements()方法,其底层实现也会调用对应的BaseExecutorflushStatements()方法。

  @Override

  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {

    try {

      List<BatchResult> results = new ArrayList<BatchResult>();

      if (isRollback) {

        return Collections.emptyList();

      }

      for (int i = 0, n = statementList.size(); i < n; i++) {

        Statement stmt = statementList.get(i);

        BatchResult batchResult = batchResultList.get(i);

        try {

          batchResult.setUpdateCounts(stmt.executeBatch());

          MappedStatement ms = batchResult.getMappedStatement();

          List<Object> parameterObjects = batchResult.getParameterObjects();

          KeyGenerator keyGenerator = ms.getKeyGenerator();

          if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {

            Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;

            jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);

          } else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141

            for (Object parameter : parameterObjects) {

              keyGenerator.processAfter(this, ms, stmt, parameter);

            }

          }

        } catch (BatchUpdateException e) {

          StringBuilder message = new StringBuilder();

          message.append(batchResult.getMappedStatement().getId())

              .append(" (batch index #")

              .append(i + 1)

              .append(")")

              .append(" failed.");

          if (i > 0) {

            message.append(" ")

                .append(i)

                .append(" prior sub executor(s) completed successfully, but will be rolled back.");

          }

          throw new BatchExecutorException(message.toString(), e, results, batchResult);

        }

        results.add(batchResult);

      }

      return results;

    } finally {

      for (Statement stmt : statementList) {

        closeStatement(stmt);

      }

      currentSql = null;

      statementList.clear();

      batchResultList.clear();

    }

  }

 

       下面是一个使用MybatisBatchExecutor进行批量操作的示例。在示例中我们创建了一个使用BatchExecutorSqlSession,也可以是SqlSessionTemplate,其实现了SqlSession接口,底层通过一个SqlSession代理进行相应的操作。然后在循环中一次调用对应Mapper的新增操作,相当于调用BatchExecutordoUpdate(),最后调用SqlSessioncommit()方法提交事务,在SqlSessioncommit()中会调用Executorcommit(),从而导致了executeBatch()的发生。

   @Test

   public void testExecutor() {

      SqlSession session = this.sessionFactory.openSession(ExecutorType.BATCH);

      UserMapper mapper = session.getMapper(UserMapper.class);

      User user = null;

      for (inti = 0; i < 10; i++) {

        user = new User();

        user.setName("Name_" + i);

        user.setEmail("email");

        mapper.insert(user);

      }

      // 批量插入User

      session.commit();// 提交事务时批量操作才会写入数据库

      session.close();

   }

 

参考文档

       Mybatis源码

 

(注:本文是基于Mybatis3.3.1所写,写于20161224日星期六)

 

 

0
0
分享到:
评论

相关推荐

    Mybatis Plus 自定义批量插入或批量更新(根据唯一索引)

    本文将深入探讨如何在 Mybatis Plus 中自定义批量插入和批量更新,并根据唯一索引来确保数据的唯一性。 首先,了解 Mybatis Plus 的批量操作基础。Mybatis Plus 提供了 `batchInsert()` 和 `batchUpdate()` 方法来...

    MyBatis的逆向工程——generatorSqlmapCustom

    MyBatis的逆向工程,也称为代码生成器或者Generator,是MyBatis框架提供的一种自动化工具,能够帮助开发者快速生成基于数据库表的Java实体类、Mapper接口与XML配置文件等,大大提高了开发效率。在本项目...

    MyBatis的逆向工程——generatorSqlmapCustom (2)

    在本篇文章中,我们将深入探讨MyBatis的逆向工程工具——generatorSqlmapCustom,这是对数据库模式进行自动生成代码的强大功能。在第一部分中,我们可能已经介绍了基础概念,现在我们将继续深入研究这一主题。 逆向...

    Spring+SpringMVC+Mybatis框架整合例子——亲测可用.zip

    SSM框架整合是Java开发中常见的技术栈,包括Spring、SpringMVC和Mybatis三个核心组件。这个压缩包提供了一个已经验证过的整合示例,帮助开发者理解和实践这三大框架的协同工作。 首先,Spring框架是Java企业级应用...

    【java框架】SpringBoot(7) -- SpringBoot整合MyBatis(csdn)————程序..pdf

    本篇将详细介绍如何在SpringBoot中整合MyBatis。 首先,我们来看一下整合MyBatis的基础步骤。SpringBoot通过引入特定的starter依赖来实现MyBatis的集成。在`pom.xml`文件中,我们需要添加以下依赖: ```xml &lt;!--...

    基于SpringBoot、JDBC、Mybatis和EasyExcel的Java Excel批量导入导出设计源码

    该项目是一款基于SpringBoot、JDBC、Mybatis和EasyExcel的Java Excel批量导入导出解决方案源码,包含22个文件,其中包括10个Java源文件、2个Markdown文件、2个XML文件、1个Git忽略文件、1个JAR包文件、1个属性文件、...

    【MyBatis入门】—— MyBatis日志

    这篇博客“【MyBatis入门】—— MyBatis日志”旨在帮助初学者理解如何在MyBatis中配置和使用日志功能,以便于调试和优化应用程序。 在MyBatis中,日志系统对于跟踪SQL语句和参数,以及检查执行效率至关重要。...

    MyBatis防止批量更新1

    MyBatis 插件机制防止批量更新 MyBatis 是一个流行的持久层框架,它提供了插件机制来拦截 SQL 操作,以便于开发者可以在执行 SQL 语句前进行预处理或后续处理。本文将详细介绍 MyBatis 插件机制的实现原理和应用...

    mybatis plus 5种批量操作性能测试

    MyBatis Plus 是 MyBatis 的一个扩展,它在 MyBatis 的基础上提供了更多的便捷功能,包括但不限于批量操作。在数据库交互中,批量操作能够显著提高效率,减少数据库连接的开销。本测试主要探讨了 MyBatis Plus 中的...

    Mybatis实现多表联合查询和批量插入

    本文将详细介绍如何使用Mybatis实现多表联合查询和批量插入。 一、多表联合查询 在实际开发中,经常需要对多个表进行联合查询,例如,查询员工信息同时需要关联部门信息和职位信息。Mybatis提供了强大的联合查询...

    SpringMVC + Mybatis 增删改查(批量删除)

    本教程将详细介绍如何使用SpringMVC和Mybatis来实现基本的增删改查(CRUD)功能,包括批量删除。 **SpringMVC** 是Spring框架的一部分,它是一个轻量级的MVC(Model-View-Controller)框架,提供了处理HTTP请求、...

    【MyBatis学习笔记一】——MyBatis入门demo.zip

    【MyBatis学习笔记一】——MyBatis入门demo.zip 博客地址:https://blog.csdn.net/weixin_43817709/article/details/117370755

    【MyBatis学习笔记二】——MyBatis配置说明.zip

    MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs...

    【MyBatis学习笔记五】——MyBatis注解的简单使用.zip

    【MyBatis学习笔记五】——MyBatis注解的简单使用.zip 博客地址:https://blog.csdn.net/weixin_43817709/article/details/117407621

    Mybatis中使用updateBatch进行批量更新

    在Mybatis中,可以使用updateBatch方法来进行批量更新,下面将详细介绍Mybatis中使用updateBatch进行批量更新的相关知识点。 逐条更新 逐条更新是指在业务代码中循环遍历逐条更新每条数据。这种方式显然是最简单,...

    Mybatis批量foreach merge into的用法

    Mybatis批量foreach merge into的用法 Mybatis批量foreach merge into的用法是通过Mybatis的动态SQL语法foreach循环插入实现的,这种方法可以批量插入时间价格表数据。如果某个套餐的某天的价格存在,则更新,不...

    SpringBoot整合Mybatis连接SQL Server 跨库批量插入

    本篇将深入探讨如何在Spring Boot项目中整合Mybatis,实现对SQL Server数据库的跨库批量插入操作。 首先,我们需要在Spring Boot项目中引入相关的依赖。对于Mybatis的支持,我们需要添加Mybatis和其Spring Boot ...

    mybatis 通用分页插件和批量操作插件

    NULL 博文链接:https://hzs0502030128.iteye.com/blog/2254585

    Mybatis批量更新三种方式的实现

    下面将介绍Mybatis批量更新三种方式的实现。 方式一:使用foreach标签 在Mybatis映射文件中,我们可以使用foreach标签来实现批量更新。例如: ``` ;"&gt; update tableName name=${item.name}, name2=${item....

Global site tag (gtag.js) - Google Analytics