上一章我们已经讲完了关于Mybatis的分页用法,其实MyBatis 还具有的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 SQL 字符串在一起是十分纠结的,确保不能忘了空格或在列表的最后省略逗号。Mybatis中的动态 SQL 可以彻底处理这种痛苦。对于动态SQL,最通俗简单的方法就是我们自己在硬编码的时候赋予各种动态行为的判断,而在Mybatis中,用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中。动态 SQL 元素和使用 JSTL 或其他相似的基于 XML 的文本处理器相似。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

  本章中我们利用前几章构建的实例,假设几种应用情况,通过实践了解这几种动态SQL标签的用法,毕竟学习最快的途径就是动手实践~

  我们常用的几个节点元素有if,choose(when, otherwise),trim(where, if),foreach。真正使用下来我感觉有点像XSLT的用法。详细用法说明(点我)

  (1)if 的用法

   还记得上一章中我们有再ViisitMapper的分页配置中看到if节点吗,如果pageIndex>-1 and pageSize>-1的时候就加入相应的分页SQL,否则就不添加(默认取全部),如下:

<select id="getListByPagenate" parameterType="PagenateArgs"
resultType="Visitor">
select * from (
<include refid="getListSql" /> <include refid="orderBySql"/>
) t <!-- #{}表示参数化输出,${}表示直接输出不进行任何转义操作,自己进行转移 -->
<if test="pageStart>-1 and pageSize>-1">
limit #{pageStart}, #{pageSize}
</if>
</select>
<sql id="getListSql">
select * from Visitor where
status>0
</sql>
<sql id="orderBySql">
order by ${orderFieldStr} ${orderDirectionStr}
</sql>

  因为我们的参数pageIndex与pageSize都是int值所以可以这样直接判断,如果是对象实例我们可以利用null判断来进行一些动态逻辑的控制,具体实际开发中就要看业务需求了。这里我认为要注意的是别十分顺手的吧and写成&&,这个在配置中不会被识别~。

  (2)choose (when, otherwise)的用法

  choose when 主要在多个条件的情况下只满足其中一个条件的应用场景中使用,例如这里就构建一个query条件,分别传递id,name与createTime。假设我们查询Visitor表时,如果VisitorId有值则,使用Id查询,如果VisitorName有值则采用VisitName查询,如下,还是在david.mybatis.demo.IVisitorOperation接口类中添加List<Visitor> getListChooseWhenDemo(BasicQueryArgs args)方法。在VisitorMapper中添加相应的的select节点配置:

package david.mybatis.demo;

import java.util.List;

import david.mybatis.model.BasicQueryArgs;
import david.mybatis.model.PagenateArgs;
import david.mybatis.model.Visitor;
import david.mybatis.model.VisitorWithRn; public interface IVisitorOperation {
/*
* 添加访问者
*/
public int add(Visitor visitor); /*
* 删除访问者
*/
public int delete(int id); /*
* 更新访问者
*/
public int update(Visitor visitor); /*
* 查询访问者
*/
public Visitor query(int id); /*
* 查询List
*/
public List<Visitor> getList(); /*
* 分页查询List
*/
public List<Visitor> getListByPagenate(PagenateArgs args); /*
* 分页查询List(包含Rownum)
*/
public List<VisitorWithRn> getListByPagenateWithRn(PagenateArgs args); /*
* 基础查询
*/
public Visitor basicQuery(int id); /*
* 动态条件查询(choose,when)实例
*/
public List<Visitor> getListChooseWhenDemo(BasicQueryArgs args); /*
* 动态条件查询(where,if)实例
*/
public List<Visitor> getListWhereDemo(BasicQueryArgs args); /*
* 动态查询(foreach)实例
*/
public List<Visitor> getListForeachDemo(List<Integer> ids); }

修改后的IvisitorOperation

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">
<resultMap type="Visitor" id="visitorRs">
<id column="Id" property="id" />
<result column="Name" property="name" />
<result column="Email" property="email" />
<result column="Status" property="status" />
<result column="CreateTime" property="createTime" />
</resultMap>
<sql id="getListSqlConditions">
select * from Visitor
</sql>
<!-- 满足其中一个条件时候用choose when操作 -->
<select id="getListChooseWhenDemo" resultMap="visitorRs"
parameterType="BasicQueryArgs">
<include refid="getListSqlConditions" />
<where>
<if test="queryStatus>0">
status=#{queryStatus}
</if>
<choose>
<when test="queryId!=0">
and id=#{queryId}
</when>
<when test="queryName!=null">
and name like #{queryName}
</when>
<otherwise>
and createTime>= #{queryTime}
</otherwise>
</choose>
</where>
</select>
</mapper>

choose-when-otherwise动态条件配置

  (3)where if (trim)的用法

  where关键词的好处是在于,如果有相应的过滤条件的话,它知道在适当的时候插入where关键词。而且它也知道在何时该去掉相应的AND与OR的连接符,主要应对如下情景

<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>

  不会因为所有条件不满足变为

<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
</select>

  或者因为没有满足第一个条件,单单满足后面的条件变成

<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’
</select>

  所以针对这种我们可以在建立choose when条件示例,同样在IVisitorOperation接口类中加入相应的方法public List<Visitor> getListWhereDemo(BasicQueryArgs args),把VisitorMapper配置文件中的相对应配置加上去如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">
<sql id="getListSqlConditions">
select * from Visitor
</sql>
<!-- 满足条件的都加上去操作 -->
<select id="getListWhereDemo" resultMap="visitorRs"
parameterType="BasicQueryArgs">
<include refid="getListSqlConditions" /> <where>
<if test="queryStatus>0">
status>0
</if>
<if test="queryId>0">
and id=#{queryId}
</if>
<if test="queryName!=null">
and name like=#{queryName}
</if>
<if test="queryTime!=null">
and createTime>=#{queryTime}
</if>
</where>
<!--
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="queryStatus>0">
status>0
</if>
<if test="queryId>0">
and id=#{queryId}
</if>
<if test="queryName!=null">
and name like=#{queryName}
</if>
<if test="queryTime!=null">
and createTime>=#{queryTime}
</if>
</trim>
-->
</select>
</mapper>

Where if动态条件配置

  (4)foreach的用法

  在常用的动态SQL中我们有个业务场景是要where id in 一大串的ID,像这种情况我们就可以用到foreach啦,不必自己辛辛苦苦去拼接Id字符串啦。同样的步骤还是在IVisitorOperation接口类中加入相应的方法public List<Visitor> getListForeachDemo(List<Integer> ids),然后再对应的Mapper文件中配置上相应的节点元素信息,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">
<sql id="getListSqlConditions">
select * from Visitor
</sql>
<!-- Foreach循环条件 -->
<select id="getListForeachDemo" resultMap="visitorRs">
<include refid="getListSqlConditions"/>
where status>0 and id in
<foreach collection="list" item="item" index="index" open="(" separator="," close=")">
${item}
</foreach>
</select>
</mapper>

Foreach动态条件配置

  最后你只需要在DemoRun中建立相应的测试方法,Mybatis里面的动态SQL也就完成啦,下面测试用的DemoRun方法

/*
* 动态查询foreach实例
*/
public static void getListForeachDemo(List<Integer> ids) {
SqlSession session = MybatisUtils.getSqlSession();
IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
List<Visitor> ls = vOperation.getListForeachDemo(ids);
for (Visitor visitor : ls) {
System.out.println(visitor);
}
} /*
* 动态查询where if实例
*/
public static void getListWhereCondition(int id, String name, Date createTime) {
name = name == "" ? null : name;
SqlSession session = MybatisUtils.getSqlSession();
BasicQueryArgs args = new BasicQueryArgs(id, name, createTime);
IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
List<Visitor> ls = vOperation.getListWhereDemo(args);
if (ls.size() == 0)
System.out.println("查无匹配!");
else {
for (Visitor visitor : ls) {
System.out.println(visitor);
}
}
} /*
* 动态查询choose when实例
*/
public static void getListChooseWhenDemo(int id, String name, Date createTime) {
name = name == "" ? null : name;
SqlSession session = MybatisUtils.getSqlSession();
BasicQueryArgs args = new BasicQueryArgs(id, name, createTime);
IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
List<Visitor> ls = vOperation.getListChooseWhenDemo(args);
if (ls.size() == 0)
System.out.println("查无匹配!");
else {
for (Visitor visitor : ls) {
System.out.println(visitor);
}
}
}

DemoRun方法

最后一章会讲述,怎么MybatisGenerator生成工具生成这些配置与文件~

一步步学Mybatis-怎么样实现动态SQL查询(6)的更多相关文章

  1. 【mybatis深度历险系列】mybatis中的动态sql

    最近一直做项目,博文很长时间没有更新了,今天抽空,学习了一下mybatis,并且总结一下.在前面的博文中,小编主要简单的介绍了mybatis中的输入和输出映射,并且通过demo简单的介绍了输入映射和输 ...

  2. Mybatis入门之动态sql

    Mybatis入门之动态sql 通过mybatis提供的各种标签方法实现动态拼接sql. 1.if.where.sql.include标签(条件.sql片段) <sql id="sel ...

  3. mybatis 详解------动态SQL

    mybatis 详解------动态SQL   目录 1.动态SQL:if 语句 2.动态SQL:if+where 语句 3.动态SQL:if+set 语句 4.动态SQL:choose(when,o ...

  4. mybatis中的动态SQL

    在实际开发中,数据库的查询很难一蹴而就,我们往往要根据各种不同的场景拼接出不同的SQL语句,这无疑是一项复杂的工作,我们在使用mybatis时,mybatis给我们提供了动态SQL,可以让我们根据具体 ...

  5. mybatis入门基础----动态SQL

    原文:http://www.cnblogs.com/selene/p/4613035.html 阅读目录 一:动态SQL 二:SQL片段 三:foreach 回到顶部 一:动态SQL 1.1.定义 m ...

  6. Mybatis映射文件动态SQL语句-01

    因为在很多业务逻辑复杂的项目中,往往不是简单的sql语句就能查询出来自己想要的数据,所有mybatis引入了动态sql语句, UserMapper.xml <?xml version=" ...

  7. SQL Server-聚焦深入理解动态SQL查询(三十二)

    前言 之前有园友一直关注着我快点出SQL Server性能优化系列,博主我也对性能优化系列也有点小期待,本来打算利用周末写死锁以及避免死锁系列的接着进入SQL Server优化系列,但是在工作中长时间 ...

  8. SQL Server-聚焦sp_executesql执行动态SQL查询性能真的比exec好?

    前言 之前我们已经讨论过动态SQL查询呢?这里为何再来探讨一番呢?因为其中还是存在一定问题,如标题所言,很多面试题也好或者有些博客也好都在说在执行动态SQL查询时sp_executesql的性能比ex ...

  9. MyBatis是支持普通 SQL查询

    MyBatis是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML或注解用于配置 ...

随机推荐

  1. .NET下用C#实现邮箱激活功能

    最近要用到安全邮箱激活的功能,故写篇博客记录下. 思路:在表中增加一个字段State来记录邮箱是否激活(0激活,1未激活.) 1.发送邮件.     1-1,给邮箱发送邮件.内容:激活地址+GUID. ...

  2. Linux环境Weblogic10g服务部署

    1.先安装XManager: 2.进入XShell,远程连接Linux主机后,按如下操作即可打开XManager配置WebLogic部署服务: [root@server36 bin]# cd /[ro ...

  3. javascript正则表达式简介

      javascript正则表达式 javascript正则表达式 regular expression是一个描述字符模式的对象: ECMAScript中的RegExp类表示正则表达式: String ...

  4. java Comparable 比较器的使用

    /** * */ package com.mindreader; import java.util.Arrays; /** * @作者 Mind reader * @内容 对象数组排序——Compar ...

  5. NServiceBus教程-NServiceBus和WCF

    WCF中缺少的最主要的事情是发布/订阅,但为什么你必须建立它自己吗?NServiceBus,你把它弄出来. 下一个重要的事情是容错.异常导致WCF代理休息,需要"刷新"的代码,但调 ...

  6. HP ILO2 使用详细教程

    iLO是Intergrated Light-Out的缩写,是惠普特有的远程管理功能,目前最新的版本是iLO2.通过iLO2可以实现硬件级别的服务器远程管理,包括开关机.重启.服务器状态的监控.虚拟KV ...

  7. 配置IIS Express 7.5以允许外部访问

    默认配置文件位于:[我的文档]\IISExpress\config\applicationhost.config修改站点地址如:<binding protocol="http" ...

  8. LINQ标准查询操作符(四) —AsEnumerable,Cast,OfType,ToArray,ToDictionary,ToList,ToLookup,First,Last,ElementAt

    十.转换操作符 转换操作符是用来实现将输入对象的类型转变为序列的功能.名称以“As”开头的转换方法可更改源集合的静态类型但不枚举(延迟加载)此源集合.名称以“To”开头的方法可枚举(即时加载)源集合并 ...

  9. MSSQL 2005数据库可疑状态

    今天早上打开进销存,提示链接失败,经过检查参数,网络.端口等各种情况,均没有发现问题,最后检查数据库本事的问题. 通过studio进去发现我的进销存数据变成了(可疑)状态,随机百度修复方法,修复方法还 ...

  10. linux下find查找命令用法

    Linux下find命令在目录结构中搜索文件,并执行指定的操作.Linux下find命令提供了相当多的查找条件,功能很强大.由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时 ...