动态映射
在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的并不只是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 前缀,所以自动省略。
判定节点并非仅限于isNotEmpty,ibatis中提供了丰富的判定定义功能。
判定节点分两类:
一元判定
一元判定是针对属性值本身的判定,如属性是否为NULL,是否为空值等。
上面示例中isNotEmpty就是典型的一元判定。
<isPropertyAvailable> 参数类中是否提供了此属性
<isNotPropertyAvailable> 与<isPropertyAvailable>相反
<isNull> 属性值是否为NULL
<isNotNull> 与<isNull>相反
<isEmpty> 如果属性为Collection或者String,其size是否<1,如果非以上两种类型,则通过String.valueOf(属性值)获得其String类型的值后,判断其size是否<1
<isNotEmpty> 与<isEmpty>相反。
二元判定
二元判定有两个判定参数,一是属性名,而是判定值,如
<isGreaterThan prepend="AND" property="age" compareValue="18">
(age=#age#)
</isGreaterThan>
其中,property="age"指定了属性名”age”,compareValue=”18”指明了判定值为”18”。
上面判定节点isGreaterThan 对应的语义是:如果age 属性大于18(compareValue),则在SQL中加入(age=#age#)条件。
二元判定节点有:
<isEqual> 相等。
<isNotEqual> 不等。
<isGreaterThan> 大于
<isGreaterEqual> 大于等于
<isLessThan> 小于
<isLessEqual> 小于等于
相关推荐
6. 关于优化iBATIS映射性能的最佳实践和技巧。 总之,"ibatis 的关系映射" 是一个涵盖广泛话题的领域,包括ORM策略、框架内部机制和开发工具的使用,对于希望深入理解和应用iBATIS的开发者来说,是非常有价值的内容...
iBATIS-SqlMaps是Java开发中的一个持久层框架,它...通过理解和熟练运用SqlMapConfig.xml和SqlMap.xml文件,开发者可以高效地实现数据的CRUD操作,同时还能享受到iBATIS提供的高级特性,如动态SQL和复杂的数据映射。
Ibatis 是一款轻量级的Java持久层框架,它提供了SQL映射文件和基于XML或注解的SQL语句配置,使得开发者可以更加灵活地控制SQL的编写,从而避免了传统的JDBC代码中的大量模板式代码。这个"ibatis SQL映射文件、DAO、...
### ibatis配置文件、映射文件详解 #### 1. SQL Map Config 文件详解 在ibatis框架中,`sqlMapConfig.xml`是一个非常重要的配置文件,它主要用于设置ibatis的全局配置信息,包括数据库连接信息、环境配置以及其它...
标题 "ibatis UPDATE 动态XML与insert" 涉及到的是MyBatis框架中对数据库数据进行更新(UPDATE)和插入(INSERT)操作的动态XML配置方式。MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射,...
标题和描述中提到的“ibatis映射文件信息,接口对应”是指Ibatis如何通过映射文件与Java接口进行关联,实现数据操作的封装和调用。 首先,我们需要了解Ibatis的核心组成部分:SqlMapConfig.xml配置文件、Mapper接口...
在Java Web开发中,iBATIS(现在被称为MyBatis)是一个流行的持久层框架,它提供了灵活的SQL映射机制,使得开发者可以更方便地操作数据库。本篇将深入讲解iBATIS一对一映射的概念、配置及应用,帮助你更好地理解和...
此文本主要是关于ibatis总配置和映射配置和一些需要主要的细节。
在IT行业中,数据库关系映射是开发Web应用时不可或缺的一部分,特别是对于ORM(对象关系映射)框架如iBATIS(现在称为MyBatis)。本文将深入探讨如何在iBATIS中实现一对多和多对多的关系映射,并提供相关的源码分析...
Ibatis,作为一个轻量级的Java ORM框架,提供了强大的功能来处理复杂的数据映射,其中包括一对多的关系映射。在这个场景下,我们将深入探讨Ibatis如何实现一对多的关系映射。 一对多关系在数据库设计中非常常见,它...
### ibatis 使用 HashMap 解决 resultClass 映射 在日常的软件开发过程中,尤其是在处理数据库查询时,我们经常面临一个问题:如何优雅地处理那些未知或动态变化的列名及列数的情况?在这种情况下,传统的实体类...
iBATIS动态标签是SQL映射文件中的一种功能强大的特性,它允许在SQL语句中进行条件判断,根据传入的参数动态生成合适的查询条件。动态标签主要用于提高灵活性,使得SQL映射文件能够适应多种查询场景,而无需为每种...
总的来说,iBATIS的继承映射利用`discriminator`列实现了对象的多态性,使得我们可以根据数据库中的信息动态地实例化合适的Java对象。这种设计大大简化了处理复杂数据库结构的代码,提高了代码的可读性和可维护性。...
5. 学习路径:对于初学者,首先需要理解Freemarker的基本语法和模板设计理念,然后学习iBatis的配置、映射和动态SQL,最后通过实践项目将两者结合。同时,阅读提供的文档和源代码,可以帮助你快速掌握这两项技术的...
iBATIS 的另一个强大特性是支持动态 SQL,可以在 SQL 映射文件中使用条件判断、循环等逻辑。例如: ```xml != null"> AND USER_NAME = #{name} ``` 这段代码表示如果 `name` 参数不为空,则在 SQL 中添加相应的 ...
### 解决IBatis缓存动态字段问题 #### 背景与问题描述 在使用IBatis框架处理数据库操作时,可能会遇到动态数据表名、动态字段名的情况。这种情况下,由于IBatis的缓存机制,可能导致字段找不到的问题。具体表现为...
功能:当你建立好数据库,写好javabean,就可以用这个工具来为你的javabean和数据库之间做一个映射. 当然这个映射只是一个大致的模板,很多时候你可能要稍做修改.但是也为你节约了很多的时间. <br>使用方法: 1....