在Spring框架中,iBatis的支持很类似JDBC或者Hibernate的支持,因为它和JDBC或Hibernate一样支持相同的模板式编程, iBatis的支持能与Spring的异常体系一起工作并让你享用所有Spring的Ioc特点。
事务管理可以由Spring标准机制进行处理。对于iBATIS来说没有特别的事务策略,除了JDBC
Connection
以外,也没有特别的事务资源。因此,Spring
标准的JDBC DataSourceTransactionManager
或者
JtaTransactionManager
已经能够完全足够了。
注意
Spring的确支持iBatis的1.x和2.x.但是,只有iBatis 2.x的支持包含在核心Spring发布版本中。 iBatis1.x的支持类被转移到Spring 2.0的Spring Modules project,你可以在那里找到文档指导。
如果我们希望使用iBATIS 2.x来映射刚才的那个Account类,则需要创建这样一个SQL map Account.xml
:
<sqlMap namespace="Account"> <resultMap id="result" class="examples.Account"> <result property="name" column="NAME" columnIndex="1"/> <result property="email" column="EMAIL" columnIndex="2"/> </resultMap> <select id="getAccountByEmail" resultMap="result"> select ACCOUNT.NAME, ACCOUNT.EMAIL from ACCOUNT where ACCOUNT.EMAIL = #value# </select> <insert id="insertAccount"> insert into ACCOUNT (NAME, EMAIL) values (#name#, #email#) </insert> </sqlMap>
iBATIS2的配置文件看起来像这样:
<sqlMapConfig> <sqlMap resource="example/Account.xml"/> </sqlMapConfig>
记住iBATIS从CLASSPATH下加载资源,所以必须确保 Account.xml
在CLASSPATH下。
我们可以使用Spring container中的 SqlMapClientFactoryBean
。
注意iBATIS SQL Map 2.x中,JDBC DataSource
通常由
SqlMapClientFactoryBean
指定,并开启了延迟加载。
<beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="WEB-INF/sqlmap-config.xml"/> <property name="dataSource" ref="dataSource"/> </bean> </beans>
SqlMapClientDaoSupport
提供了类似 SqlMapDaoSupport
的功能。我们可以继承它来实现我们自己的DAO:
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao { public Account getAccount(String email) throws DataAccessException { return (Account) getSqlMapClientTemplate().queryForObject("getAccountByEmail", email); } public void insertAccount(Account account) throws DataAccessException { getSqlMapClientTemplate().update("insertAccount", account); } }
我们可以在application context中创建了 SqlMapAccountDao
并且注入 SqlMapClient
实例,这样我们就可以在DAO中使用预先配置的
SqlMapClientTemplate
来执行查询了:
<beans> <bean id="accountDao" class="example.SqlMapAccountDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> </beans>
注意 SqlMapTemplate
实例也可以手工创建,使用
SqlMapClient
作为构造函数参数。
SqlMapClientDaoSupport
基类为我们预先初始化了一个
SqlMapClientTemplate
实例。
SqlMapClientTemplate
还提供了一个通用的
execute
方法,将用户自定义的 SqlMapClientCallback
的实现作为参数。举例来说,这可以实现批量操作:
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao { public void insertAccount(Account account) throws DataAccessException { getSqlMapClientTemplate().execute(new SqlMapClientCallback() { public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException { executor.startBatch(); executor.update("insertAccount", account); executor.update("insertAddress", account.getAddress()); executor.executeBatch(); } }); } }
一般来说,任何由 SqlMapExecutor
API提供的操作组合都以这样的回调形式被使用。
而在这个过程中产生的任何 SQLException
都将被自动地转化为Spring的通用的 DataAccessException
异常体系。
你也可以基于原生的iBATIS API来编程,而无需对Spring产生任何依赖。直接使用注入的
SqlMapClient
。一个相应的DAO实现类看上去就像下面这样:
public class SqlMapAccountDao implements AccountDao { private SqlMapClient sqlMapClient; public void setSqlMapClient(SqlMapClient sqlMapClient) { this.sqlMapClient = sqlMapClient; } public Account getAccount(String email) { try { return (Account) this.sqlMapClient.queryForObject("getAccountByEmail", email); } catch (SQLException ex) { throw new MyDaoException(ex); } } public void insertAccount(Account account) throws DataAccessException { try { this.sqlMapClient.update("insertAccount", account); } catch (SQLException ex) { throw new MyDaoException(ex); } } }
在这种情况下,由iBATIS API抛出的 SQLException
异常需要以
用户自定义的方式进行处理:通常封装成为你的应用程序自身的DAO异常。在application context
中进行的整合看上去依然像以前一样,这是由于基于原生的iBATIS的DAO依然遵循IoC的模式:
<beans> <bean id="accountDao" class="example.SqlMapAccountDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> </beans>