今天看下Mybatis动态的拼装sql怎么实现。
标签:
if
choose (when, otherwise)
trim (where, set)
foreach
条件判断
第一种是if
<selectid="findActiveBlogWithTitleLike"resultType="Blog">SELECT*FROMBLOGWHEREstate=‘ACTIVE’<iftest="title1 != null">ANDtitlelike#{title} </if><iftest="title2 != null">ANDtitlelike#{title} </if> ... </select>
注意:test 的参数值需要包含查找掩码或通配符字符
第二种是choose、when、otherwise
<selectid="findActiveBlogLike"resultType="Blog">SELECT*FROMBLOGWHEREstate=‘ACTIVE’<choose><whentest="title != null">ANDtitlelike#{title} </when><whentest="author != null and author.name != null">ANDauthor_namelike#{author.name} </when><otherwise>ANDfeatured=1</otherwise></choose></select>
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。上面例子传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员精选的 Blog)。
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。我一般会在where后面加一个 1=1 ,然后再加if等标签来保证不会出现以下情形:
SELECT*FROMBLOGWHERE
可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trimprefix="WHERE"prefixOverrides="AND |OR "> ... </trim>
prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:
<updateid="updateAuthorIfNecessary">updateAuthor<set><iftest="username != null">username=#{username},</if><iftest="password != null">password=#{password},</if><iftest="email != null">email=#{email},</if><iftest="bio != null">bio=#{bio}</if></set>whereid=#{id} </update>
遍历集合 foreach
<selectid="selectPostIn"resultType="domain.blog.Post">SELECT*FROMPOSTPWHEREIDin<foreachitem="item"index="index"collection="list"open="("separator=","close=")">#{item} </foreach></select>
可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
总结:
不管用啥标签,只要注意动态拼装出来的sql保证正确即可。
END