Ibatis startBatch () only works with native SqlMapClient startup and commit transactions, not Spring-managed

I found that even if I have Spring wrapped code and it commits / rolls back when I expect to use the JDBC package when using Ibatis and Spring, I need to use the explicit SqlMapClient transaction methods.

those. this makes dosing as I expected:

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 transaction open and close statements and rely on Spring to manage things (this is what I want to do!), batch execution just doesn't happen.

Given that Spring seems to be handling its side of the transaction management transaction, can anyone advise any known issues here?

(The database is MySQL, I know about the problems with the JDBC pseudo-batch approach with rewriting the INSERT statement, which is definitely not a problem)

+4
source share
2 answers

I found the reason for this, after reading various resources and trial and error, I wrote down our results here, as this may help someone else.

It turns out that different types of behavior were associated with our DAO classes extending Spring SqlMapClientTemplate. In this class, you have two "choices" (I say the choice, one is correct, in fact it is not):

  • direct use of insert (), update (), etc .; using full Spring objects completely

  • getSqlMapClient (). insert (), update (), etc .; this one actually works using the com.ibatis ... object returned by getSqlMapClient (), not Spring one

Both generally work, but from my reading the first option is better, for example. if you use Spring, you want to be completely Spring, and not "jump" onto Ibatis objects.

Now SqlMapClientTemplate does not provide access to startBatch () / executeBatch () directly, just a convenient insert (), update (), so this code is necessary to do this. The code below works fully with our Spring-driven transactions, not the explicit startTransaction () code in sight.

(a disclaimer may contain errors due to my "anonymous" 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); } }); } } 

Link: http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/orm/ibatis/SqlMapClientTemplate.html

+2
source

The reason is this. If you do not open the transaction. iBatis will complete the transaction after calling the insert statement. For more information, you can check the code in com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate

0
source

Source: https://habr.com/ru/post/1311096/


All Articles