1.mybatis默认支持使用ognl表达式来生成动态sql语句

MyBatis中可以使用OGNL的地方有两处:

  • 动态SQL表达式中
  • ${param}参数中

上面这两处地方在MyBatis中处理的时候都是使用OGNL处理的。

2.Mybatis <where>标签

<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>

如果这些条件没有一个能匹配上将会怎样?最终这条 SQL 会变成这样:

SELECT * FROM BLOG
WHERE

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:

SELECT * FROM BLOG
WHERE
AND title like ‘yiibai.com’

这个查询也会失败。这个问题不能简单的用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不想再这样去写了。

MyBatis 有一个简单的处理,这在90%的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能得到想要的效果:

<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>

where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。

如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制我们想要的功能。比如,和 where 元素等价的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>

今天遇到一个场景需要写一个这样的查询语句:

用户对象userInfo包含下面几个字段: 
userName phone email qqId weiboId wxId

现在新注册用户,传过来一个注册userInfo对象,现在要到数据库中验证状态status=1 (表示激活的用户)的用户中,是否存在一个用户,只要它这些字段中至少有一个与新注册的对象对应的字段内容相同,那就说明重复注册。

翻译成sql语句表示一下的意思大概就是: 
select * from tablename where 

userName=”xxx” 
or phone =”xxx” 
or … 

and status=1

一开始我是这样写的,在mybatis中的代码就是这样:

<select id="selectBySelective" resultType="xxx.UserInfo">
select
<include refid="Base_Column_List" />
from uc_user
<where>
(<if test="userName != null" >
user_name = #{userName}
</if>
<if test="email != null" >
or email = #{email}
</if>
<if test="phone != null" >
or phone = #{phone}
</if>
<if test="weiboId != null" >
or weibo_id = #{weiboId}
</if>
<if test="wxId != null" >
or wx_id = #{wxId}
</if>
<if test="qqId != null" >
or qq_id = #{qqId}
</if>)
</where>
and status = 1
</select>

这样代码看似没有什么问题但是其实是有问题的。为什么呢? 
如果userName 为空,后面某字段不为空,最后的sql语言会成为这样:

select * from uc_user where(or email = "xxx") and status = 1

使用mybatis < where > 标签就是为了防止这种情况,mybatis会在第一个 
userName 为空的情况下,帮我们去掉后面的语句的第一个”or”

但是我加了where标签中加入()后,语句会报错。因为自动去掉”or”会失效。

查看了mybatis官方文档发现了另一个标签 < trim >可以通过自定义 trim 元素来定制我们想要的功能

trim标签包围的内容可以设置几个属性: 
prefix :内容之前加的前缀 
suffix :内容之后加的后缀 
prefixOverrides: 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的,多个忽略序列用“|”隔开)。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除。

所以我修改后的代码是:

 <select id="selectBySelective" resultType="xxx.UserInfo">
select
<include refid="Base_Column_List" />
from uc_user
<trim prefix="WHERE (" suffix=")" prefixOverrides="AND |OR ">
<if test="userName != null" >
user_name = #{userName}
</if>
<if test="email != null" >
or email = #{email}
</if>
<if test="phone != null" >
or phone = #{phone}
</if>
<if test="weiboId != null" >
or weibo_id = #{weiboId}
</if>
<if test="wxId != null" >
or wx_id = #{wxId}
</if>
<if test="qqId != null" >
or qq_id = #{qqId}
</if>
</trim>
and status = 1
</select>

ok搞定。

  1. <select id="getStudentList_if" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity">
  2. SELECT ST.STUDENT_ID,
  3. ST.STUDENT_NAME,
  4. ST.STUDENT_SEX,
  5. ST.STUDENT_BIRTHDAY,
  6. ST.STUDENT_PHOTO,
  7. ST.CLASS_ID,
  8. ST.PLACE_ID
  9. FROM STUDENT_TBL ST
  10. WHERE
  11. <if test="studentName !=null ">
  12. ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%')
  13. </if>
  14. <if test="studentSex != null and studentSex != '' ">
  15. AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER}
  16. </if>
  17. <if test="studentBirthday != null ">
  18. AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE}
  19. </if>

最新文章

  1. 从备考PMP到与项目经理同呼吸
  2. 【好玩的前端知识】 Kube
  3. Centos6 修改max user processes limits
  4. RouterOS软路由设置固定IP+PPPOE
  5. Crusher Django 学习笔记4 使用Model
  6. java程序练习:猜字母
  7. LINUX下解决netstat查看TIME_WAIT状态过多问题
  8. CSS3学习--dispaly:inline和float:left两者区别
  9. Java数学表示式解析工具- jeval
  10. js求字符长度
  11. RMAN备份各种物理文件
  12. Dom7.js 源码阅读备份
  13. C++ vector的用法(整理)
  14. Bigger-Mai 养成计划,Python基础巩固一
  15. bootstrap概述
  16. Windows下Codeblocks调试Cocos2d-x项目体验(一次失败的体验)
  17. Django models 常用数据类型
  18. BZOJ2321 [BeiJing2011集训] 星器
  19. JAVA核心技术I---JAVA基本程序设计结构
  20. LA 3523 圆桌骑士(二分图染色+点双连通分量)

热门文章

  1. Python学习 Day 5 高阶函数 map/reduce filter sorter 返回函数 匿名函数 装饰器 偏函数
  2. [Android]AndroidDesign中ActionBar探究2 嵌入Fragment
  3. Bing图片下载器(Python实现)
  4. qt 5中文乱码
  5. swift class extension 与继承
  6. OpenMP入门教程(一)
  7. CS2QS
  8. delphi byte to of set
  9. 51node 1134 最长递增子序列 (数据结构)
  10. 看完这篇 你就能完全操作git 远程分支的增、删、改、查了