mybatis中的动态SQL语句
有时候,静态的SQL语句并不能满足应用程序的需求。我们可以根据一些条件,来动态地构建 SQL语句。
例如,在Web应用程序中,有可能有一些搜索界面,需要输入一个或多个选项,然后根据这些已选择的条件去执行检索操作。我们可能需要根据用户选择的条件来构建动态的SQL语句。如果用户提供了任何一个条件,我们需要将那个条件添加到SQL语句的WHERE子句中。
!以下内容基于自己建的表和类!
1.<if>标签被用来通过条件嵌入SQL片段,如果条件为true,则相应地SQL片段将会被添加到SQL语句中。
例如:
假定有一个课程搜索界面,设置了讲师(Tutor)下拉列表框,课程名称(CourseName)文本输入框,开始时间(StartDate)输入框,结束时间(EndDate)输入框,作为搜索条件。假定课讲师下拉列表是必须选的,其他的都是可选的。当用户点击搜索按钮时,需要显示符合条件的列表数据。
对应的sql映射文件,如下所示:
<!-- 独立的Course封装映射 -->
<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>
<!-- 查询Course的select语句,里面加入了if条件判断 -->
<select id="searchCourses" parameterType="map" 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 <![CDATA[ <= ]]> #{endDate}
</if>
</select>
映射接口:
public interface DynamicSqlMapper{
List<Course> searchCourses(Map<String, Object> map);
}
测试方法:
@Test
public void test_searchCourses1(){ SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); Map<String,Object> map = new HashMap<String,Object>();
map.put("tutorId", 1);
map.put("courseName", "%Java%"); LocalDate date = LocalDate.of(2019, 1, 10);
map.put("startDate", date); List<Course> courses = mapper.searchCourses(map); courses.forEach(System.out::println); } catch (Exception e) {
e.printStackTrace();
}
}
2.choose,when 和 otherwise 条件
有时候,查询功能是以查询类别为基础的。首先,用户需要先选择是通过讲师查询,还是课程名称查询,还是开始时间查询。然后根据选择的查询类别,输入相应的参数,再进行查询。
例如,页面中有一个下拉列表,可以选择查询的类别,可以选择根据讲师查询、根据课程名查询、根据时间查询等等,选择了列表之后,再输入关键字进行查询。
MyBatis提供了<choose>标签可以支持此类型的查询处理。 假设如果用户都没有选择,那么默认可以根据当前时间进行查询。
注意:mysql中now()表示当前时间 oracle需要使用sysdate
对应的sql映射文件,如下所示:
<select id="searchCourses" parameterType="map" 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 start_date >= sysdate
</otherwise>
</choose>
</select>
测试方法:
@Test
public void test_searchCourses2(){ SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); Map<String,Object> map = new HashMap<String,Object>();
// map.put("searchBy", "Tutor");
// map.put("tutorId", 1);
map.put("searchBy", "CourseName");
map.put("courseName", "%MyBatis%"); List<Course> courses = mapper.searchCourses(map); courses.forEach(System.out::println); } catch (Exception e) {
e.printStackTrace();
}
}
MyBatis计算<choose>中条件的值,并使用第一个值为TRUE的子句。如果没有条件为 true,则使用<otherwise>内的子句。
3.Where 条件
有时候,所有的查询条件应该是可选的。在需要使用至少一种查询条件的情况下,可以直接使用WHERE子句。
如果有多个条件,我们需要在条件中添加AND或OR。MyBatis提供了<where>元素支持这种类型的动态SQL语句。
例如,在查询课程界面,假设所有的查询条件是可选的。
注意,<where>元素只有在其内部标签有返回内容时才会在动态语句上插入WHERE条件语句。
并且,如果WHERE子句以AND或者OR打头,则打头的AND或OR将会被移除。
映射文件:
<select id="searchCourses" parameterType="map" 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>
</where>
</select>
测试方法:
@Test
public void test_searchCourses3(){ SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); Map<String,Object> map = new HashMap<String,Object>();
//map.put("tutorId", 1);
//map.put("courseName", "JavaSE");
//map.put("startDate", LocalDate.of(2019, 1, 10)); List<Course> courses = mapper.searchCourses(map); courses.forEach(System.out::println); } catch (Exception e) {
e.printStackTrace();
}
}
4.<trim>条件
<trim>元素和<where>元素类似,但是<trim>提供了添加 前缀/后缀 或者 移除 前缀/后缀 的功能。
映射文件:
<select id="searchCourses" parameterType="map" resultMap="CourseResult">
SELECT * FROM COURSES
<trim prefix="WHERE" suffixOverrides="and">
<if test=" tutorId != null ">
TUTOR_ID = #{tutorId} and
</if>
<if test="courseName != null">
name like #{courseName} and
</if>
</trim>
</select>
prefix表示有一个if成立则插入where语句,没有if成立,就会去掉where直接查询
suffix表示后缀,和prefix相反
suffixOverrides="and"表示如果最后生成的sql语句多一个and,则自动去掉.
prefixOverrides的意思是处理前缀,和suffixOverrides相反
测试方法:
@Test
public void test_searchCourses4(){ SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); Map<String,Object> map = new HashMap<String,Object>();
// map.put("tutorId", 1);
// map.put("courseName", "JavaSE"); List<Course> courses = mapper.searchCourses(map); courses.forEach(System.out::println); } catch (Exception e) {
e.printStackTrace();
}
}
5.foreach 循环
另外一个强大的动态SQL语句构造标签是<foreach>。它可以迭代遍历一个数组或者列表,构造AND/OR条件或一个IN子句。
假设查询tutor_id为 1,3,6的讲师所教授的课程,我们可以传递一个tutor_id组成的列表给映射语句,然后通过<foreach>遍历此列表构造动态SQL。
映射文件:
<select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult">
SELECT * FROM COURSES
<if test="tutorIds != null">
<where>
<!-- 在这里的 tutorId指的是集合中存入准备查询的tutor_id-->
<foreach item="tutorId" collection="tutorIds">
OR tutor_id = #{tutorId}
</foreach>
</where>
</if>
</select>
映射接口:
public interface DynamicSqlMapper{
List<Course> searchCoursesByTutors(Map<String,Object> map);
}
测试方法:
@Test
public void test_searchCoursesByTutors(){ SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); 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); List<Course> courses = mapper.searchCoursesByTutors(map); courses.forEach(System.out::println); } catch (Exception e) {
e.printStackTrace();
}
}
和上面同样的功能,使用<foreach>生成IN子句:
<select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult">
SELECT * FROM COURSES
<if test="tutorIds != null">
<where>
tutor_id IN
<foreach item="tempValue" collection="tutorIds" open="(" separator="," close=")">
#{tempValue}
</foreach>
</where>
</if>
</select>
测试方法保持不变。
6.set 条件,专用于UPDATE更新操作
<set>元素和<where>元素类似,但是set元素只是针对update更新语句使用的。
<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=#{studId}
</update>
这里,如果<if>条件返回了任何文本内容,<set>将会插入set关键字和其文本内容,并且会剔除将末尾的逗号","。
测试方法:
@Test
public void test_updateStudent(){ SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); Student student = new Student();
student.setStudId(45);
student.setEmail("xx@briup.com"); mapper.updateStudent(student); sqlSession.commit(); } catch (Exception e) {
e.printStackTrace();
}
}
mybatis中的动态SQL语句的更多相关文章
- 阶段3 1.Mybatis_08.动态SQL_01.mybatis中的动态sql语句-if标签
创建新的工程 复制到新建的项目里面 pom.xml依赖部分复制过来 dao中整理代码 只保留四个查询 映射文件也只保留四个查询方法 增加一个根据条件查询的方法. 由于用了别名,所以parpameter ...
- 【mybatis深度历险系列】mybatis中的动态sql
最近一直做项目,博文很长时间没有更新了,今天抽空,学习了一下mybatis,并且总结一下.在前面的博文中,小编主要简单的介绍了mybatis中的输入和输出映射,并且通过demo简单的介绍了输入映射和输 ...
- mybatis中的动态SQL
在实际开发中,数据库的查询很难一蹴而就,我们往往要根据各种不同的场景拼接出不同的SQL语句,这无疑是一项复杂的工作,我们在使用mybatis时,mybatis给我们提供了动态SQL,可以让我们根据具体 ...
- Mybatis映射文件动态SQL语句-01
因为在很多业务逻辑复杂的项目中,往往不是简单的sql语句就能查询出来自己想要的数据,所有mybatis引入了动态sql语句, UserMapper.xml <?xml version=" ...
- 6.Mybatis中的动态Sql和Sql片段(Mybatis的一个核心)
动态Sql是Mybatis的核心,就是对我们的sql语句进行灵活的操作,他可以通过表达式,对sql语句进行判断,然后对其进行灵活的拼接和组装.可以简单的说成Mybatis中可以动态去的判断需不需要某些 ...
- mybatis 学习五 动态SQL语句
3.1 selectKey 标签 在insert语句中,在Oracle经常使用序列.在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键.使用myBatis的selectKey ...
- 存储过程中执行动态Sql语句
MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...
- 怎样SQL存储过程中执行动态SQL语句
MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...
- mybatis中实现动态SQL
动态SQL语句,也就意味着SQL语句不在是一成不变的而是具有多样性. if if的用法还是跟平常差不多的(不过没有else if也没有else) <update id="modify& ...
随机推荐
- A. Srdce and Triangle--“今日头条杯”首届湖北省大学程序设计竞赛(网络同步赛)
如下图这是“今日头条杯”首届湖北省大学程序设计竞赛的第一题,作为赛后补题 题目描述:链接点此 这套题的github地址(里面包含了数据,题解,现场排名):点此 Let be a regualr tr ...
- thinkphp+layui多图上传(1)thinkphp5+layui实现多图上传保存到数据库,可以实现图片自由排序,自由删除。
公共css代码 <style> .layui-upload-img { width: 90px; height: 90px; margin: 0; } .pic-more { width: ...
- node.js是用来做什么的
Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.(事件驱动:事件触发过程中,进行决策的一种策略,简单说就是跟随当前时间点上出现的事物,调用可用的资源进行解决该事物,使得不 ...
- Java学习之集合(List接口)
List特有的常见方法:有一个共性特点:都可以操作角标 1.添加 void add(int index, E element); void addAll(int index, collection& ...
- php5模块pdo、pdo_mysql、mysqli的添加
一.环境LAMP都是源码安装,PHP安装的时候没有配置pdo_mysql和mysqli,pdo是php5默认带的.PHP5的源码都在,只需要把php5的模块功能扩展就可以了. php源码目录:/usr ...
- kuangbin专题十三-基础计算几何
链接:https://cn.vjudge.net/contest/68968 POJ 2318 TOYS 题意:m个玩具落在n+1个区间,给你玩具的坐标,问每个区间有多少玩具. 思路:叉积的简单应用, ...
- python3 可变数据类型和不可变数据类型
python内置有6种对象类型: Number 数值型 int 整型 不可变 float 浮点型 不可变 complex 复数 不可变 String 字符串 不可变 Tuple 元组 不可变 ...
- 并发编程之CAS(二)
更多Android架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从以下几个内容来阐述CAS: [CAS原理] [CAS带来的ABA问题] 一 ...
- java-day20
注解:说明程序的,给计算机看的 注释:用文字描述程序的,给程序员看的 定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性.与类.接口.枚举是在 ...
- 6-MySQL-Ubuntu-操作数据表的基本操作(一)
注: SQL语句的关键字不区分大小写,如select 和Select都可以 (1) 查看当前使用的数据库; select database(); (2) 使用某数据库或切换到某数据库 use 数据库名 ...