在使用
iBatis
的
sqlmap
时,总是有些疑惑,
DAO
是怎么找到
sqlmap
的配置文件的呢,
DAO
是怎么获得数据库的配置信息的呢,这些又是怎么和
Spring
整合在一起的呢?带着这些疑问,鄙人试图通过对某个项目的代码分析,来理清这些头绪。
当我们书写一个
DAO
实现类时,首先
implement
一个
DAO
接口。然后继承
BaseDAO
类。这个类对
Spring
的
DaoSupport
类作了扩展,提供了两个重要的方法
setDataSource()
和
setSqlMapClient()
。
setDataSource()
方法用来设置数据源,从而确定数据库配置信息。而
setSqlMapClient()
用来设置
SqlMapClient
,就是
SqlMapClient
确定了
sqlmap
的配置。其整个静态结构如下图所示:
图
1
在上图中,
BaseDAO
的
setDataSource()
和
setSqlMapClient()
方法实际上是分别调用了
SqlMapClientTemplate
类对象
sqlMapClientTemplate
的
setDataSource()
和
setSqlMapClient()
方法。其中
setDataSource()
方法是
SqlMapClientTemplate
类通过继承
JdbcAccessor
类获得。
下面讲讲这一切是怎么和
Spring
整合到一起的。
我们在
spring
的
bean
配置文件配置
DAO
,比如拿
admPacVoucherDAO
为例:
<bean
id=
"admPacVoucherDAO"
class=
"com.counter.biz.dal.ibatis.IbatisAdmPacVoucherDAO"
parent=
"sqlMapClientDAO"
/>
|
IbatisAdmPacVoucherDAO继承了BaseDAO类,对于继承来的属性,这里用parent="sqlMapClientDAO" 来获得。sqlMapClientDAO是另一个bean,这个bean就是BaseDAO的实例!也就是说,只要看看这个bean是怎么写的,就可以知道admPacVoucherDAO这个DAO怎么配置起来的。这一点可以从图一中看出来。
我们找到
sqlMapClientDAO
的声明如下:
<bean
id=
"sqlMapClientDAO"
class=
"com.counter.biz.dal.BaseDAO"
>
<property
name=
"sqlMapClient"
>
<ref
bean=
"sqlMapClient"
/>
</property>
<property
name=
"dataSource"
>
<ref
bean=
"dataSource"
/>
</property>
</bean>
|
果然,其中有
sqlMapClient
和
dataSource
属性。好!继续追下去,我们看看
sqlMapClient
这个
bean
的声明:
<bean
id=
"sqlMapClient"
class=
"org.springframework.orm.ibatis.SqlMapClientFactoryBean"
>
<property
name=
"configLocation"
>
<value>
counter/persistence/counter-sqlmap.xml
</value>
</property>
</bean>
|
哈哈,找到
sqlmap
配置文件在哪里指定了,就是这里。
configLocation
指定了配置文件的位置。打开看看果然是各个
sqlmap
的配置:
<?xml
version=
"1.0"
encoding=
"GB2312"
?>
<!DOCTYPE
sqlMapConfig
PUBLIC
"-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd"
>
<sqlMapConfig>
<settings
cacheModelsEnabled=
"true"
enhancementEnabled=
"false"
lazyLoadingEnabled=
"false"
maxRequests=
"3000"
maxSessions=
"3000"
maxTransactions=
"3000"
useStatementNamespaces=
"false"
/>
<sqlMap
resource=
"counter/sqlmap/pacioli-sql-mapping.xml"
/>
<sqlMap
resource=
"counter/sqlmap/common-sqlmap-mapping.xml"
/>
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
<sqlMap
resource=
"com/counter/biz/dal/sqlmap/PacVoucherDebitInfo-sqlmap-mapping.xml"
/>
<sqlMap
resource=
"com/counter/biz/dal/sqlmap/PacVoucherExt-sqlmap-mapping.xml"
/>
</sqlMapConfig>
|
可是再看看
sqlMapClient
这个
bean
的类型,疑惑又来了。这个
bean
根本不是
SqlMapClient
类的实例,甚至似乎和
SqlMapClient
没有任何联系。这个
bean
的类型是
SqlMapClientFactoryBean
。原来这是一个工厂类,这个类负责组装
SqlMapClient
类的实例。这个类有
getObject()
和
getObjectType()
方法。
getObject()
返回的就是
SqlMapClient
类的实例,而
getObjectType()
方法返回
SqlMapClient
类。这种工厂方法很有意思,笔者会在以后对种方式作深入研究。
当我通过
spring
的
IoC
获得
DAO
的
bean
,并执行其中一个方法,比如:
public
int
getDebitCountByVoucherId(Long
voucherId)
{
Integer
count
=
(Integer)
this
.getSqlMapClientTemplate().queryForObject(
"MS-PAC-VOUCHER-DEBIT-COUNT-BY-VOUCHERID"
,
voucherId);
return
count.intValue();
}
|
实际是获得
SqlMapClientTemplate
类对象,并执行其中的方法。而通过上文可以得知,
SqlMapClientTemplate
类对象通过获得的
sqlMapClient
就可以得到所有
sqlmap
的配置。