笔记:MyBatis 动态SQL
有时候,静态的SQL语句并不能满足应用程序的需求。我们可以根据一些条件,来动态地构建SQL语句。例如,在Web应用程序中,有可能有一些搜索界面,需要输入一个或多个选项,然后根据这些已选择的条件去执行检索操作。在实现这种类型的搜索功能,我们可能需要根据这些条件来构建动态的SQL语句。如果用户提供了任何输入条件,我们需要将那个条件 添加到SQL语句的WHERE子句中。
MyBatis通过使用<if>,<choose>,<where>,<foreach>,<trim>元素提供了对构造动态SQL语句的高级别支持。
- if
语句
<if>元素被用来有条件地嵌入SQL片段,如果测试条件被赋值为true,则相应地SQL片段将会被添加到SQL语句中。
假定我们有一个课程搜索界面,设置了 讲师(Tutor)下拉列表框,课程名称(CourseName)文本输入框,开始时间(StartDate)输入框,结束时间(EndDate)输入框,作为搜索条件。假定课讲师下拉列表是必须选的,其他的都是可选的。
当用户点击 搜索按钮时,我们需要显示符合以下条件的成列表:
- 特定讲师的课程
- 课程名包含输入的课程名称关键字的课程;如果课程名称输入为空,则取所有课程
- 在开始时间和结束时间段内的课程
我们可以对应的映射语句,如下所示:
<resultMap
type="Course"
id="CourseResult">
<id
column="course_id"
property="courseId"
/>
<result
column="name"
property="name"
/>
<result
column="description"
property="description"
/>
<result
column="start_date"
property="startDate"
/>
<result
column="end_date"
property="endDate"
/>
</resultMap>
<!-- 查询输入参数定义为 hashmap 类型 -->
<select
id="searchCourses"
parameterType="hashmap"
resultMap="CourseResult">
SELECT * FROM COURSES
WHERE TUTOR_ID= #{tutorId}
<if
test="courseName != null">
AND NAME LIKE #{courseName}
</if>
<if
test="startDate != null">
AND START_DATE >= #{startDate}
</if>
<if
test="endDate != null">
AND END_DATE <= #{endDate}
</if>
</select>
Java代码如下:
public interface CourseMapper
{
List<Course> searchCourses(Map<String, Object> map);
}
public
void
searchCourses()
{
Map<String, Object> map = new HashMap<String, Object>();
map.put("tutorId", 1);
map.put("courseName", "%java%");
map.put("startDate", new
Date());
CourseMapper mapper = sqlSession.getMapper(CourseMapper.class);
List<Course> courses = mapper.searchCourses(map);
for (Course course : courses)
{
System.out.println(course);
}
}
- choose,when 和otherwise 条件
有时候,查询功能是以查询类别为基础的。首先,用户需要选择是否希望通过选择讲师,课程名称,开始时间,或结束时间作为查询条件类别来进行查询,然后根据选择的查询类别,输入相应的参数。在这样的情景中,我们需要只使用其中一种查询类别。
MyBatis 提供了<choose>元素支持此类型的SQL预处理。
现在让我们书写一个适用此情景的SQL映射语句。如果没有选择查询类别,则查询开始时间在今天之后的课程,代码如下:
<select
id="searchCourses"
parameterType="hashmap"
resultMap="CourseResult">SELECT * FROM COURSES
<choose>
<when
test="searchBy == 'Tutor'">WHERE TUTOR_ID= #{tutorId}
</when>
<when
test="searchBy == 'CourseName'">WHERE name like #{courseName}
</when>
<otherwise>
WHERE TUTOR start_date >= now()
</otherwise>
</choose>
</select>
MyBatis计算<choose>测试条件的值,且使用第一个值为TRUE的子句。如果没有条件为true,则使用<otherwise>内的子句。
- where
条件
有时候,所有的查询条件(criteria)应该是可选的。在需要使用至少一种查询条件的情况下,我们应该使用WHERE子句。并且, 如果有多个条件,我们需要在条件中添加AND或OR。MyBatis提供了<where>元素支持这种类型的动态SQL语句。
在我们查询课程界面,我们假设所有的查询条件是可选的。进而,当需要提供一个或多个查询条件时,应该改使用WHERE子句。
<select
id="searchCourses"
parameterType="hashmap"
resultMap="CourseResult">SELECT * FROM COURSES
<where>
<if
test=" tutorId != null ">TUTOR_ID= #{tutorId}
</if>
<if
test="courseName != null">AND name like #{courseName}
</if>
<if
test="startDate != null">AND start_date >= #{startDate}
</if>
<if
test="endDate != null">AND end_date <= #{endDate}
</if>
</where>
</select>
<where>元素只有在其内部标签有返回内容时才会在动态语句上插入WHERE条件语句。并且,如果WHERE子句以AND或者OR打头,则打头的AND或OR将会被移除。如果tutor_id参数值为null,并且courseName参数值不为null,则<where>标签会将AND name like#{courseName} 中的AND移除掉,生成的SQL WHERE子句为:where name like#{courseName}。
- trim条件
<trim>元素和<where>元素类似,但是<trim>提供了在添加前缀/后缀 或者移除前缀/后缀方面提供更大的灵活性
<select
id="searchCourses"
parameterType="hashmap"
resultMap="CourseResult">SELECT * FROM COURSES
<trim
prefix="WHERE"
prefixOverrides="AND | OR"><if
test=" tutorId != null ">TUTOR_ID= #{tutorId}
</if>
<if
test="courseName != null">AND name like #{courseName}
</if>
</trim>
</select>
这里如果任意一个<if>条件为true,<trim>元素会插入WHERE,并且移除紧跟WHERE后面的AND或OR
- foreach循环
另外一个强大的动态SQL语句构造标签即是<foreach>。它可以迭代遍历一个数组或者列表,构造AND/OR条件或一个IN子句。
假设我们想找到tutor_id为1,3,6的讲师所教授的课程,我们可以传递一个tutor_id组成的列表给映射语句,然后通过<foreach>遍历此列表构造动态SQL。
注意:如果参数类型为
List
则其 <foreach…/> 的
collection
设置为
list,如果为
map
则设置为集合的
key
名称。<select
id="searchCoursesByTutors"
parameterType="map"
resultMap="CourseResult">SELECT * FROM COURSES
<if
test="tutorIds != null"><where>
<foreach
item="tutorId"
collection="tutorIds">OR tutor_id=#{tutorId}
</foreach>
</where>
</if>
</select>
Java代码:
public interface CourseMapper
{
List<Course> searchCoursesByTutors(Map<String, Object> map);
}
public
void
searchCoursesByTutors(){
Map<String, Object> map = new HashMap<String, Object>();
List<Integer> tutorIds = new ArrayList<Integer>();
tutorIds.add(1);
tutorIds.add(3);
tutorIds.add(6);
map.put("tutorIds", tutorIds);
CourseMapper mapper =
sqlSession.getMapper(CourseMapper.class);
List<Course> courses = mapper.searchCoursesByTutors(map);
for (Course course : courses)
{
System.out.println(course);
}
}
现在让我们来看一下怎样使用<foreach>生成 IN子句:
<select
id="searchCoursesByTutors"
parameterType="map"
resultMap="CourseResult">SELECT * FROM COURSES
<if
test="tutorIds != null"><where>
tutor_id IN
<foreach
item="tutorId"
collection="tutorIds" open="("
separator=","
close=")">#{tutorId}
</foreach>
</where>
</if>
</select>
- set条件
<set>元素和<where>元素类似,如果其内部条件判断有任何内容返回时,他会插入SET SQL片段。
<update
id="updateStudent"
parameterType="Student">update students
<set>
<if
test="name != null">name=#{name},</if><if
test="email != null">email=#{email},</if><if
test="phone != null">phone=#{phone},</if></set>
where stud_id=#{id}
</update>
这里,如果<if>条件返回了任何文本内容,<set>将会插入set关键字和其文本内容,并且会剔除将末尾的 ","。
在上述的例子中,如果 phone!=null,<set>将会让会移除 phone=#{phone}后的逗号",",生成 set phone=#{phone} 。
笔记:MyBatis 动态SQL的更多相关文章
- MyBatis:学习笔记(4)——动态SQL
MyBatis:学习笔记(4)——动态SQL 如果使用JDBC或者其他框架,很多时候需要你根据需求手动拼装SQL语句,这是一件非常麻烦的事情.MyBatis提供了对SQL语句动态的组装能力,而且他只有 ...
- MyBatis:学习笔记(4)——动态SQL
MyBatis:学习笔记(4)——动态SQL
- mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句
mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. c ...
- mybatis原理分析学习记录,mybatis动态sql学习记录
以下个人学习笔记,仅供参考,欢迎指正. MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转 ...
- 记Mybatis动态sql
目录 记MyBatis动态SQL 1.< SQL >标签 2.< if >标签 3.分支标签 1.第一种:用在查询条件上用choose-when:otherwise可不要 2. ...
- 9.mybatis动态SQL标签的用法
mybatis动态SQL标签的用法 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...
- 自己动手实现mybatis动态sql
发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客.本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧. 用过mybatis的人,估计 ...
- Mybatis动态SQL单一基础类型参数用if标签
Mybatis动态SQL单一基础类型参数用if标签时,test中应该用 _parameter,如: 1 2 3 4 5 6 <select id="selectByName" ...
- 超全MyBatis动态SQL详解!( 看完SQL爽多了)
MyBatis 令人喜欢的一大特性就是动态 SQL. 在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的. MyBatis 动态 SQL 的出现, 解决了这个麻烦. My ...
- Mybatis动态SQL简单了解 Mybatis简介(四)
动态SQL概况 MyBatis 的强大特性之一便是它的动态 SQL 在Java开发中经常遇到条件判断,比如: if(x>0){ //执行一些逻辑........ } Mybatis应用中,S ...
随机推荐
- windows下用pip安装软件超时解决方案
以前介绍过ubuntu下更换更新源办法,详情见http://www.cnblogs.com/Alier/p/6358447.html 下面讲一下windows下面pip的配置更改,包括下载软件是超时错 ...
- 【Unity3D】Unity3D开发《我的世界》之一、创建一个面
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/unity_minecraft_01.html 最近总有人问及我的游戏里跟<我的世界>一样的地形是如何实 ...
- Android常见Crash类型分析(一)
问题1. java.lang.IllegalStateException: The specified child already has a parent. You must call remo ...
- 错误:readline/readline.h:没有那个文件或目录解决方法
curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz tar zxf lua-5.3.0.tar.gz cd lua-5.3.0 make linux ...
- java中final和static
final的意思是最终的,最后的额,不可变的,在java中也具有相似的含义. final修饰基础数据表示把该数据修饰成常量,意味着不可修改,不可变. final修饰对象的引用的时候,表示该引用不可变, ...
- C# 通过smtp服务器进行邮件发送 MailHelper
C# 通过smtp服务器进行邮件发送 MailHelper.cs using System; using System.Data; using System.Configuration; using ...
- 异常-----spring明明注入了Service到Action中,为什么运行的时候Service为空,在抽象类中,有子类来继承的
xml的配置文件 <bean id="fftController" class="com.bill99.query.controller.FftController ...
- 用winscp从本地上传文件到服务器上出现复制文件到远端时错误。
用winscp从本地上传文件到服务器上出现复制文件到远端时错误. 错误码:4 服务器返回的错误消息:write failed 报错如下图所示: 分析过程: 1.刚开始以为是权限不够,后面上网查了一下是 ...
- beautifulsoup库使用
介绍与安装 Beautiful Soup 是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据.BeautifulSoup 用来解析 HTML 比较简单, API非常人 ...
- Python机器学习中文版
Python机器学习简介 第一章 让计算机从数据中学习 将数据转化为知识 三类机器学习算法 第二章 训练机器学习分类算法 透过人工神经元一窥早期机器学习历史 使用Python实现感知机算法 基于Iri ...