返回介绍

9.2 批量更新

发布于 2025-04-26 13:08:35 字数 2616 浏览 0 评论 0 收藏

在数据库中使用批量更新有助于提高性能。在 MyBatis 中,我们可以修改配置文件中 settings 的 defaultExecutorType 来制定其执行器为批量执行器,如代码清单 9-5 所示。

代码清单 9-5:配置批量执行器

<settings>
......
  <setting name="defaultExecutorType" value="BATCH"/>
......
</settings>

当然我们也可以用 Java 代码来实现批量执行器的使用,如代码清单 9-6 所示。

代码清单 9-6:打开批量 SqlSession

sqlSessionFactory.openSession(ExecutorType.BATCH);

如果你是在 Spring 环境中使用批量执行器,也可以这样定义 Spring 的 Bean,如代码清单 9-7 所示。

代码清单 9-7:Spring 环境下的批量执行器

<bean id="sqlSessionTemplate" 
class="org.mybatis.spring.SqlSessionTemplate">     
  <constructor-arg index="0" ref="sqlSessionFactory" />  
  <!--更新采用批量模式 -->  
  <constructor-arg index="1" value="BATCH"/>  
  </bean>  

批量执行需要注意的问题是,一旦使用了批量执行器,那么在默认的情况下,它在 commit 后才发送 SQL 到数据库,此时我们需要注意代码清单 9-8 所示的问题。

代码清单 9-8:批量执行器问题代码

        SqlSession session = SqlSessionFactoryUtil.openSqlSession();
        try {
            RoleMapper rmapper = session.getMapper(RoleMapper.class);
            Role role = new Role();
            role.setRoleNo("role_no_xxx");
            role.setRoleName("role_name_xxx");
            role.setRoleNo("role_note_xxx");
            rmapper.insertRole(role);
            Role role2 = rmapper.getRole("role_no_xxx");
            System.err.println(role2.getRoleName());
            session.commit();
        } catch(Exception ex) {
            session.rollback();
            ex.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }

我们运行上面的代码后,出现了下面这行代码:

System.err.println(role2.getRoleName());

抛出空异常,然后事务回滚。

从代码上看,我们先插入了 role 到数据库,它运行了代码 role2 依旧为空,所以打印其名称的时候将抛出异常,为什么会这样呢?由于我们采用了批量的执行器,则更新数据 SQL 的执行操作是要到 session.commit() 中才会被 MyBatis 发送到数据库执行的,所以在我们执行下面的操作之前,insert 在数据库中根本没有被执行,于是便出现了这句话获取一个空对象的情况。这是我们需要注意的。

Role role2 = rmapper.getRole("role_no_xxx");

而我们在 getRole 方法调用前并不想提交事务,因为后面可能还有其他更新的数据库语句要执行,这个时候我们只要执行 SqlSession 的 flushStatements 方法便可以了,它的含义是将当前缓存的 SQL 发送给数据库执行。于是我们按照代码清单 9-9 的方法修改代码。

代码清单 9-9:在获取数据前发送 SQL

    RoleMapper rmapper = session.getMapper(RoleMapper.class);
    Role role = new Role();
    role.setRoleNo("role_no_xxx");
    role.setRoleName("role_name_xxx");
    role.setNote("role_note_xxx");
    rmapper.insertRole(role);
    session.flushStatements();
    Role role2 = rmapper.getRole("role_no_xxx");
    System.err.println(role2.getRoleName());
    session.commit();

这样就避免了在一个事务里面插入了数据,而 select 查不出来的情况,代码就能运行成功了,我们在使用批量更新的时候要特别注意这个问题。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。