|
Thanks for the report! I assume you access your SqlMapClient directly rather than via Spring's SqlMapClientTemplate: The effect only shows on such direct access, as SqlMapClientTemplate will always override the transaction config with a Spring-managed JDBC Connection. Note that direct SqlMapClient access does not participate in Spring-managed transactions! This means you will always execute non-transactionally, at least if not using JTA. You could also use the iBATIS SqlMapTransactionManager API, of course, but that's not recommended in a Spring environment. The effect was caused by a bad iBATIS default for ExternalTransactionConfig: It sets the JDBC Connection to manual commit mode but never issues commit or rollback... I've modified SqlMapClientFactoryBean to suppress this by default, always keeping the original autoCommit value as provided by the connection pool. So SqlMapClientFactoryBean's default behavior should be fine now: plain non-transactional execution (usually in auto-commit mode as provided by the pool) if there is no external transaction. Nevertheless, I've also added a "transactionConfigClass" property to SqlMapClientFactoryBean, allowing to specify the iBATIS TransactionConfig class to use (for example, JdbcTransactionConfig). There's also "transactionConfigProperties", allowing to customize the properties passed to the iBATIS TransactionConfig instance. Furthermore, I've modified SqlMapClientFactoryBean's DataSource handling to pass a transaction-aware DataSource proxy to the SqlMapClient. This finally allows lazy loading and direct SqlMapClient access to participate in Spring-managed transactions, while still working properly without Spring transaction management! Juergen Juergen, you have solved my problem. I did not mean to use IBatis directly. Incorrectly, I was using getSqlMapClient instead of getSqlMapClientTemplate. I was not clear on this from the documentation. All seems to work fine with DBCP now when i use the template. Sorry i missed that. Thanks, Well, good that you made me aware of the issue anyway Furthermore, this issue also affects lazy loading: iBATIS shouldn't switch the Connection to manual commit there. That should all work now, both with SqlMapClientTemplate and direct SqlMapClient access. Juergen Juergen, To clarify this: With 1.1.3 can I use iBATIS transactions with SqlMapClient and have my SqlMapClientDaoSupport subclasses that are using SqlMapClientTemplate still participate in the transaction? With 1.1.2 I am seeing some weird failures combining my code and don't yet have time to convert the other utility to use Spring. If this can be done, what steps do I have to perform? Please respond as soon as possible since I'm on a rush deadline. Thanks! Robert MacDonald Robert, Transactions driven by the iBATIS SqlMapTransactionManager API will work if you specify "com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig" as "transactionConfigClass" on SqlMapClientFactoryBean. This is not the recommended transaction demarcation style, though: It's preferable to use Spring driven transactions. As of Spring 1.1.3, Spring-driven transactions will even work with with plain SqlMapClient access, as long as the SqlMapClient instance used by the DAOs is set up by SqlMapClientFactoryBean. Juergen Hello Juergen, I think I have problems with managing transactions. I'm using IBATIS and Spring together. I set SqlMapClientFactoryBean's datasource and configLocation with my sql-map-config.xml. My DAO classes extend SqlMapClientDaoSupport and in my methods I call my mapping sql statetements with sqlMapClientTemplate. In which layer do I have to implement transaction managing? Here is a snippet from my DAO class; public class ActivitySqlMapDAO extends SqlMapClientDaoSupport implements ActivityDAO { For example the activity is inserted, it doesn't rollback, when this method throws a division by zero exception. Thanks in advance. |
|||||||||||||||||||||||||||||||||||||||||
Here is the diff from CVS of the code change:
> import com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig;
> import com.ibatis.sqlmap.engine.transaction.BaseTransactionConfig;
63a66,67
> private boolean externalTransactionManager = true;;
>
101a106,109
> public void setUseExternalTransactionManager(boolean bUseExternalTransactionManager) { > this.externalTransactionManager = bUseExternalTransactionManager; > }
>
120c128,135
< ExternalTransactionConfig transactionConfig = new ExternalTransactionConfig();
—
> BaseTransactionConfig transactionConfig = null;
> if (!externalTransactionManager) { > transactionConfig = new JdbcTransactionConfig(); > }
> else { > transactionConfig = new ExternalTransactionConfig(); > }