我在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批处理语句。
答案 0 :(得分:1)
我没有收到任何回复,所以我会分享我确定的解决方案。
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();
}
答案 1 :(得分:1)
对不起,您的回复很晚,但是我现在偶然发现了这个问题。但是,希望它可以帮助其他有类似问题的人。
您不需要显式自动连接SqlSession。您可以使用映射器界面本身。在映射器接口中,只需定义一个用@Flush
批注注释并且返回类型为List<BatchResult>
的方法。这是映射器界面中方法的示例:
@Flush
List<BatchResult> flushBatchedStatements();
然后只需在您的mapper对象上调用此方法,如下所示:
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文档的状态:
如果使用此注释,则可以称为 SqlSession#flushStatements()通过Mapper定义的方法 界面。(MyBatis 3.3或更高版本)
有关更多详细信息,请访问MyBatis官方文档网站:
http://www.mybatis.org/mybatis-3/java-api.html