mybatis中的动态SQL语句
2019-10-16 08:18:20来源:博客园 阅读 ()
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(); } }
原文链接:https://www.cnblogs.com/Magic-Li/p/11683937.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Feign【首次请求失败】
下一篇:MyBatis详解 一篇就够啦
- MyBatis中的$和#,用不好,准备走人! 2020-06-11
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 2020-06-11
- Spring Boot 2.3.0 新特性Redis 拓扑动态感应 2020-06-11
- 构造函数中的this()和super() 2020-06-10
- 怎么用Java 高效提取、替换、删除PDF文档中的图片 2020-06-09
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash