ibatis和mybatis中的BatchExecutor


ibatis中的的處理方法

 

spring集成了ibatis的批量提交的功能,我們只要調用API就可以了
首先在你的dao中需要繼承org.springframework.orm.ibatis.support.SqlMapClientDaoSupport
然后在代碼中調用getSqlMapClientTemplate方法, 獲取SqlMapClientTemplate對象,然后做處理
 
public void insertInfos(List<Info> records) {
        if (null == records || records.size() == 0) {
            return;
        }
        // 執行回調
        SqlMapClientTemplate sqlMapClientTemplate = iBatisDaoLS13.getSqlMapClientTemplate();
        sqlMapClientTemplate.execute(new SqlMapClientCallback() {
            // 實現回調接口
            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
                // 開始批處理, for循環里面的sql必須一致,否則會創建新的PreparedStatement
                executor.startBatch();
                for (Info info : records) {
                    executor.insert(NAMESPACE + "insertAInfo", info);
                }
                // 執行批處理
                executor.executeBatch();
                return null;
            }
        });
    }

 

 

 

mybatis中的的處理方法

   在程序中,有時候我們需要批量的去操作一些數據,批量的新增、修改、刪除,如果是通過for循環一條記錄一條記錄的去更新無疑效率會比較慢。更佳的做法無疑是采用JDBC對批處理的支持。Mybatis基於JDBC對批處理的支持,也提供了進行數據的批量操作的API,BatchExecutor。下面是一段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()對應的底層代碼是調用對應的Statement的addBatch()方法。那它是在什么時候執行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()時調用,在這個時候都會調用Executor的flushStatements()方法,而BaseExecutor在執行flushStatements()時最終會調用其doFlushStatements()方法。當然,我們也可以手動的調用SqlSession的flushStatements()方法,其底層實現也會調用對應的BaseExecutor的flushStatements()方法。

  @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();

    }

  }

 

       下面是一個使用Mybatis的BatchExecutor進行批量操作的示例。在示例中我們創建了一個使用BatchExecutor的SqlSession,也可以是SqlSessionTemplate,其實現了SqlSession接口,底層通過一個SqlSession代理進行相應的操作。然后在循環中一次調用對應Mapper的新增操作,相當於調用BatchExecutor的doUpdate(),最后調用SqlSession的commit()方法提交事務,在SqlSession的commit()中會調用Executor的commit(),從而導致了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();

   }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM