【问题标题】:Ibatis startBatch() only works with SqlMapClient's own start and commit transactions, not with Spring-managed onesibatis startBatch() 仅适用于 SqlMapClient 自己的启动和提交事务,不适用于 Spring 管理的事务
【发布时间】:2010-05-27 14:09:54
【问题描述】:

我发现即使我有 Spring 事务包装的代码,并且它会在我期望的时候提交/回滚,为了在使用 Ibatis 和 Spring 时使用 JDBC 批处理,我需要使用显式 SqlMapClient 事务方法.

即这会像我期望的那样进行批处理:

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

但是如果我没有打开和关闭事务语句,并且依赖 Spring 来管理事情(这是我想做的!),批处理就不会发生。

鉴于 Spring 似乎在处理事务管理方面的讨价还价,任何人都可以就这里的任何已知问题提出建议吗?

(数据库是 MySQL;我知道它的 JDBC 伪批处理方法与 INSERT 语句重写有关的问题,这绝对不是问题)

【问题讨论】:

    标签: java mysql spring ibatis


    【解决方案1】:

    通过阅读各种资源和反复试验找到了这背后的原因,我在这里记录了我们的结果,因为它可能对其他人有所帮助。

    事实证明,不同的行为是由于我们的 DAO 类扩展了 Spring 的 SqlMapClientTemplate。在那堂课上,你有两个“选择”(我说选择;一个是正确的,一个真的不是):

    • 直接使用insert()、update()等;一直使用完整的 Spring 对象

    • getSqlMapClient().insert()、update()等;这个实际上是使用 getSqlMapClient() 返回的 com.ibatis... 对象,而不是 Spring 对象

    两者通常工作,但从我的阅读来看,第一个选项更好,例如如果您使用的是 Spring,您希望完全基于 Spring,而不是“跳出”到 Ibatis 对象。

    现在,SqlMapClientTemplate 不提供对 startBatch()/executeBatch() 的直接访问,只提供方便的 insert()、update() 东西,因此需要这样的代码来执行此类操作。下面的代码完全适用于我们的 Spring 托管事务,而不是显式代码 startTransaction()。

    (免责声明,由于我的“匿名”工作代码为清晰起见,这可能包含错误)

    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

    【讨论】:

      【解决方案2】:

      原因是。如果您不打开交易。 iBatis 将在调用插入语句后提交事务。 更多信息可以查看 com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate 中的代码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-09
        • 2013-02-09
        • 2015-12-29
        • 2012-05-24
        • 1970-01-01
        • 2012-12-26
        • 1970-01-01
        相关资源
        最近更新 更多