java Ibatis startBatch() 仅适用于 SqlMapClient 自己的启动和提交事务,不适用于 Spring 管理的事务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2921840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ibatis startBatch() only works with SqlMapClient's own start and commit transactions, not with Spring-managed ones
提问by Brian
I'm finding that even though I have code wrapped by Spring transactions, and it commits/rolls back when I would expect, in order to make use of JDBC batching when using Ibatis and Spring I need to use explicit SqlMapClient transaction methods.
我发现即使我有 Spring 事务包装的代码,并且它在我期望的时候提交/回滚,为了在使用 Ibatis 和 Spring 时利用 JDBC 批处理,我需要使用显式的 SqlMapClient 事务方法。
I.e. this does batching as I'd expect:
即这会按照我的预期进行批处理:
dao.getSqlMapClient().startTransaction();
dao.getSqlMapClient().startBatch();
int i = 0;
for (MyObject obj : allObjects)
{
dao.storeChange(obj);
i++;
if (i % DB_BATCH_SIZE == 0)
{
dao.getSqlMapClient().executeBatch();
dao.getSqlMapClient().startBatch();
}
}
dao.getSqlMapClient().executeBatch();
dao.getSqlMapClient().commitTransaction();
but if I don't have the opening and closing transaction statements, and rely on Spring to manage things (which is what I want to do!), batching just doesn't happen.
但是如果我没有开始和结束交易语句,并且依靠 Spring 来管理事情(这就是我想要做的!),批处理就不会发生。
Given that Spring does otherwise seem to be handling its side of the bargain regarding transaction management, can anyone advise on any known issues here?
鉴于 Spring 似乎正在处理有关事务管理的讨价还价方面的问题,有人可以就这里的任何已知问题提出建议吗?
(Database is MySQL; I'm aware of the issues regarding its JDBC pseudo-batch approach with INSERT statement rewriting, that's definitely not an issue here)
(数据库是 MySQL;我知道有关其 JDBC 伪批处理方法与 INSERT 语句重写的问题,这绝对不是这里的问题)
采纳答案by Brian
Found the reason behind this one through reading various resources and trial and error, I've recorded our outcomes here as it may help someone else.
通过阅读各种资源和反复试验找到了这背后的原因,我在这里记录了我们的结果,因为它可能对其他人有所帮助。
Turns out that the different behaviours were due to our DAO classes extending Spring's SqlMapClientTemplate. In that class you have two "choices" (I say choices; one's correct, one really isn't):
事实证明,不同的行为是由于我们的 DAO 类扩展了 Spring 的 SqlMapClientTemplate。在那个课上你有两个“选择”(我说的是选择;一个是正确的,一个真的不是):
direct use of insert(), update(), etc; using full Spring objects all the way
getSqlMapClient().insert(), update(), etc; this one actually works using a com.ibatis... object as returned by getSqlMapClient(), rather than a Spring one
直接使用insert()、update()等;一直使用完整的 Spring 对象
getSqlMapClient().insert()、update() 等;这个实际上使用 com.ibatis... 对象,由 getSqlMapClient() 返回,而不是 Spring 对象
Both generally work, but from my reading the first option is better, e.g. if you're using Spring you want to be fully Spring-based, not "jump out" to Ibatis objects.
两者通常都有效,但从我的阅读来看,第一个选项更好,例如,如果您使用 Spring,您希望完全基于 Spring,而不是“跳出”到 Ibatis 对象。
Now, SqlMapClientTemplate doesn't provide access to startBatch() / executeBatch() directly, just the handy insert(), update() stuff, so code such as this is necessary to do that kind of stuff. The below code works fully with our Spring managed transactions, and not an explicit code startTransaction() in sight.
现在,SqlMapClientTemplate 不直接提供对 startBatch()/executeBatch() 的访问,只提供方便的 insert()、update() 内容,因此需要诸如此类的代码来执行此类操作。下面的代码完全适用于我们的 Spring 托管事务,而不是显式代码 startTransaction() 。
(disclaimer this may contain errors due to my "anonymising" working code for clarity)
(免责声明,为了清楚起见,由于我的“匿名”工作代码,这可能包含错误)
public class MyFunkyDao extends SqlMapClientDaoSupport
{
private static final int DB_BATCH_SIZE = 1000;
public void storeMyData(final List<MyData> listData)
{
getSqlMapClientTemplate().execute( new SqlMapClientCallback()
{
@Override
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException
{
int count = 0, total = 0;
Map<String, Object> params = new HashMap<String, Object>();
executor.startBatch();
for (MyData data: listData)
{
params.put("param name 1", data.getValue());
executor.insert("insertData", params);
count++;
if (count % DB_BATCH_SIZE == 0)
{
total += executor.executeBatch();
executor.startBatch();
}
params.clear();
}
total += executor.executeBatch();
return new Integer(total);
}
});
}
}
链接:http: //static.springsource.org/spring/docs/2.5.x/api/org/springframework/orm/ibatis/SqlMapClientTemplate.html
回答by Doan Nguyen Minh Nhat
The reason is. If you don't open a transaction. iBatis will commit the transaction after an insert statement is called. For more information you can check the code in com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate
原因是。如果您不打开交易。iBatis 会在调用 insert 语句后提交事务。有关更多信息,您可以查看 com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate 中的代码

