广告位联系
返回顶部
分享到

MyBatis执行批处理操作的实现

java 来源:互联网 作者:佚名 发布时间:2024-07-09 18:10:17 人浏览
摘要

在MyBatis中,批处理操作是一种高效执行多条语句的方式,特别是当你需要在一个事务中插入、更新或删除多条记录时。批处理可以显著减少与数据库的交互次数,从而提高性能。 执行批处理的

在MyBatis中,批处理操作是一种高效执行多条语句的方式,特别是当你需要在一个事务中插入、更新或删除多条记录时。批处理可以显著减少与数据库的交互次数,从而提高性能。

执行批处理的基本步骤

  • 开启批处理模式:在获取SqlSession时,需要指定执行器(Executor)类型为ExecutorType.BATCH。
  • 执行SQL语句:执行需要批处理的SQL语句,此时语句并不会立即执行,而是被添加到批处理队列中。
  • 提交事务:调用SqlSession.commit()方法,此时MyBatis会将批处理队列中的语句一次性发送给数据库执行。
  • 处理批处理结果:提交事务后,可以通过批处理结果进行后续处理。

示例代码

1

2

3

4

5

6

7

8

9

try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {

    YourMapper mapper = sqlSession.getMapper(YourMapper.class);

    for (YourData data : dataList) {

        // 根据需要调用insert, update或delete方法

        mapper.insertOrUpdate(data);

    }

    sqlSession.commit();

    // 可以获取批处理结果,处理特定逻辑

}

深入源码解析

在MyBatis中,批处理的核心是BatchExecutor,这是Executor的一个实现。在开启批处理模式时,MyBatis会使用BatchExecutor来处理SQL会话。

BatchExecutor的关键方法

  • doUpdate: 当执行insert、update、delete方法时,BatchExecutor会将这些操作存储在内部的批处理队列中,而不是立即执行它们。
  • doFlushStatements: 当调用commit或flushStatements时,BatchExecutor会执行批处理队列中的所有SQL语句。这些操作是通过JDBC的PreparedStatement.executeBatch()方法执行的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

@Override

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

    final Configuration configuration = ms.getConfiguration();

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

    final BoundSql boundSql = handler.getBoundSql();

    final String sql = boundSql.getSql();

    final Statement stmt;

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

        int last = statementList.size() - 1;

        stmt = statementList.get(last);

        applyTransactionTimeout(stmt);

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

    } else {

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

        stmt = handler.prepare(connection, transaction.getTimeout());

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

        currentSql = sql;

        currentStatement = ms;

        statementList.add(stmt);

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

    }

    handler.batch(stmt);

    return BATCH_UPDATE_RETURN_VALUE;

}

执行批处理

当调用commit或flushStatements时,BatchExecutor.doFlushStatements会被触发,它负责实际执行批处理操作。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

@Override

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

    try {

        if (isRollback) {

            return Collections.emptyList();

        }

 

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

        if (statementList.size() > 0) {

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

                        }

                    }

                } finally {

                    closeStatement(stmt);

                }

            }

        }

        return results;

    } finally {

        for (Statement stmt : statementList) {

            closeStatement(stmt);

        }

        currentSql = null;

        statementList.clear();

        batchResultList.clear();

    }

}

小结

MyBatis的批处理通过BatchExecutor实现,它通过将SQL语句收集到批处理队列中,然后在适当的时候(如调用commit)一次性执行,以提高性能。正确使用批处理可以在执行大量类似操作时大幅度减少应用与数据库的交互次数,优化应用性能。不过,要注意批处理可能会对事务管理、错误处理等方面带来额外的复杂性,使用时需要特别留意。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计