2

我在 mybatis 中的批处理语句超时。我想通过定期刷新语句来限制我发送到数据库的负载。在 iBATIS 中,我使用了回调,如下所示:

        sqlMapClientTemplate.execute(new SqlMapClientCallback<Integer>() {
            @Override
            public Integer doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                executor.startBatch();
                int tally = 0;
                for (Foo foo: foos) {
                        executor.insert("FooSql.insertFoo",foo.getData());
                        /* executes batch when > MAX_TALLY */
                    tally = BatchHelper.updateTallyOnMod(executor, tally);
                }
                return executor.executeBatch();
            }
        });

在mybatis中有没有更好的方法来做到这一点?还是我需要用 SqlSessionCallback 做同样的事情?这感觉很麻烦。我真正想做的是配置项目以刷新每 N 个批处理语句。

4

2 回答 2

3

我没有得到任何回复,所以我将分享我确定的解决方案。

Mybatis 提供了对语句刷新的直接访问。我自动装配了 SqlSession,使用 Guava 将集合划分为可管理的块,然后在每个块之后刷新语句。

Iterable<List<Foo>> partitions = Iterables.partition(foos, MAX_TALLY);
for (List<Foo> partition : partitions) {
    for (Foo foo : partition) {
        mapper.insertFoo(foo);
    }
    sqlSession.flushStatements();
}
于 2013-02-26T22:02:06.160 回答
2

很抱歉回复晚了,但我现在偶然发现了这个问题。但是,希望它可以帮助其他有类似问题的人。

您不需要显式地自动装配 SqlSession。您可以使用映射器接口本身。在 mapper 接口中,只需定义一个使用注解进行@Flush注解的方法,并且返回类型为List<BatchResult>. 以下是映射器接口中的方法示例:

@Flush
List<BatchResult> flushBatchedStatements();

然后只需在您的映射器对象上调用此方法,如下所示:

Iterable<List<Foo>> partitions = Iterables.partition(foos, MAX_TALLY);
for (List<Foo> partition : partitions)
{
    for (Foo foo : partition)
    {
        mapper.insertFoo(foo);
    }
    mapper.flushBatchedStatements(); //this call will flush the all statements batched upto this point, into the table.
}

请注意,您无需在映射器 XML 文件中添加任何特殊内容即可通过映射器接口支持此类语句刷新。您的 XML 映射器可能只是类似于

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace=".....">

    <insert id="bulkInsertIntoTable" parameterType="myPackage.Foo">

        insert into MyDatabaseTable(col1, col2, col3)
        values
        ( #{fooObj.data1}, #{fooObj.data2}, #{fooObj.data3} )

    </insert>

</mapper>

唯一需要的是您使用 MyBatis 3.3 或更高版本。以下是 MyBatis 网站上的 MyBatis 文档状态:

如果使用这个注解,可以通过Mapper接口定义的方法调用SqlSession#flushStatements()。(MyBatis 3.3或以上)

更多详细信息请访问 MyBatis 官方文档站点:
http ://www.mybatis.org/mybatis-3/java-api.html

于 2018-07-27T23:13:58.357 回答