当前位置: 首页 > 图文教程 > Java技术 > Web框架 > Web框架:浅谈iBATIS的动态映射

Web框架
Web框架:Struts标记库定制JSP标记
Web框架:简述Ajax技术的那些框架
Web框架:利用列表数据提高开发效率
Web框架:Struts2中声明式异常处理
Web框架:小议Spring的异常处理那点事
Web框架:详谈AOP概念
Web框架:小编浅谈Struts2的Ajax支持
Web框架:Ajax提供的div标签
Web框架:程序员之家七月份Web框架总结
Web框架:浅谈Spring Bean封装机制
Web框架:小编浅谈Struts配置文件
Web框架:小编谈Spring中的AOP 应用
Web框架:Spring的闪亮之处:事务管理
Web框架:浅谈iBATIS的动态映射
Web框架:Hibernate中五个接口那些事
Web框架:Hibernate的ORM与Hibernate的优点
Web框架:Struts2的OGNL
Web框架:Struts中的ActionForm 作为防火墙
Web框架:小编浅谈Struts2中使用JSON插件实现Ajax
Web框架:Aegis绑定那些事

Web框架:浅谈iBATIS的动态映射


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 139 ::
收藏到网摘: n/a

小编之前和大家探讨过iBATIS框架的一些技术,今天小编和大家探讨的是iBATIS的动态映射,在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的

并不只是SQL 中的参数,包括Select 语句中所包括的字段和限定条件,都可能发生变

化。典型情况,如在一个复杂的组合查询页面,我们必须根据用户的选择和输入决定查

询的条件组合。

下面咱们以一个登陆功能为例,相信大家都了解吧,在这就不给图片例子了,对于这个组合查询页面,根据用户选择填写的内容,我们应为其生成不同的查询语句。如用户没有填写任何信息即提交查询请求,我们应该返回所有记录:

Select * from t_user

如用户只在页面上填写了姓名“Erica”,我们应该生成类似:

Select * from t_user where name like %Erica%

SQL查询语句。

如用户只在页面上填写了地址“Beijing”,我们应该生成类似:

Select * from t_user where address like %Beijing%”;

SQL

而如果用户同时填写了姓名和地址(”Erica&Beijing’),则我们应生成类似:

Select * from t_user where name like ‘%Erica%’ and address like ‘%Beijing%”

SQL查询语句。

对于ibatis 这样需要预先指定SQL 语句的ORM 实现而言,传统的做法无非通过

if-else 语句对输入参数加以判定,然后针对用户选择调用不同的statement 定义。对于

上面这种简单的情况(两种查询条件的排列组合,共4 种情况)而言,statement 的重

复定义工作已经让人不厌其烦,而对于动辄拥有七八个查询条件,乃至十几个查询条件

的排列组合而言,琐碎反复的statement定义实在让人不堪承受。

考虑到这个问题,ibatis引入了动态映射机制,即在statement定义中,根据不同的

查询参数,设定对应的SQL语句。还是以上面的示例为例:

<select id="getUsers"

parameterClass="user"

resultMap="get-user-result">

select

id,

name,

sex

from t_user

<dynamic prepend="WHERE">

<isNotEmpty prepend="AND" property="name">

(name like #name#)

</isNotEmpty>

<isNotEmpty prepend="AND" property="address">

(address like #address#)

</isNotEmpty>

</dynamic>

</select>

通过dynamic 节点,我们定义了一个动态的WHERE 子句。此WHERE 子句中将

可能包含两个针对name address 字段的判断条件。而这两个字段是否加入检索取决

于用户所提供的查询条件(字段是否为空[isNotEmpty])。

对于一个典型的Web程序而言,我们通过HttpServletRequest获得表单中的字段名

并将其设入查询参数,如:

user.setName(request.getParameter("name"));

user.setAddress(request.getParameter("address"));

sqlMap.queryForList("User.getUsers", user);

在执行queryForList("User.getUsers", user)时,ibatis 即根据配置文

件中设定的SQL动态生成规则,创建相应的SQL语句。

上面的示例中,我们通过判定节点isNotEmpty,指定了关于name address

性的动态规则:

<isNotEmpty prepend="AND" property="name">

(name like #name#)

</isNotEmpty>

这个节点对应的语义是,如果参数类的"name"属性非空(isNotEmpty,即非空

字符串””),则在生成的SQL Where字句中包括判定条件(name like #name#),其

#name#将以参数类的name属性值填充。

Address属性的判定生成与name属性完全相同,这里就不再赘述。

这样,我们通过在statement 定义中引入dynamic 节点,很简单的实现了SQL

定子句的动态生成,对于复杂的组合查询而言,这将带来极大的便利。

判定节点的定义可以非常灵活,我们甚至可以使用嵌套的判定节点来实现复杂的动

态映射,如:

<isNotEmpty prepend="AND" property="name">

( name=#name#

<isNotEmpty prepend="AND" property="address">

address=#address#

</isNotEmpty>

)

</isNotEmpty>

这段定义规定,只有用户提供了姓名信息时,才能结合地址数据进行查询(如果只

提供地址数据,而将姓名信息忽略,将依然被视为全检索)。

Dynamic节点和判定节点中的prepend属性,指明了本节点中定义的SQL子句在

主体SQL中出现时的前缀。

如:

<dynamic prepend="WHERE">

<isNotEmpty prepend="AND" property="name">

(name like #name#)

</isNotEmpty>

<isNotEmpty prepend="AND" property="address">

(address like #address#)

</isNotEmpty>

</dynamic>

假设"name"属性的值为“Erica, "address"属性的值为“Beijing”,则会

生成类似下面的SQL子句(实际运行期将生成带占位符的PreparedStatement,之

后再为其填充数据):

WHERE (name like ‘Beijing’) AND (address like ‘Beijing’)

其中WHERE 之后的语句是在dynamic 节点中所定义,因此以dynamic 节点的

prepend设置("WHERE")作为前缀,而其中的”AND”,实际上是address属性所对

应的isNotEmpty节点的prepend设定,它引领了对应节点中定义的SQL子句。至于

name属性对应的isNotEmpty节点,由于ibatis会自动判定是否需要追加prepend

前缀,这里(name like #name#)WHERE 子句中的第一个条件子句,无需AND

缀,所以自动省略。