Mybatis中动态SQL
来源:互联网 发布:淘宝债权转让车 经历 编辑:程序博客网 时间:2024/05/21 15:40
Mybatis中动态SQL
有时候,静态的SQL语句并不能满足应用程序的需求。我们可以根据一些条件,来动态地构建 SQL语句。例如,在Web应用程序中,有可能有一些搜索界面,需要输入一个或多个选项,然后根据这些已选择的条件去执行检索操作。在实现这种类型的搜索功能,我们可能需要根据这些条件来构建动态的SQL语句。如果用户提供了任何输入条件,我们需要将那个条件添加到SQL语句的WHERE子句中。MyBatis通过使用<if>,<choose>,<where>,<foreach>,<trim>元素提供了对构造动态SQL语句的高级别支持。
3.6.1 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> <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); }测试类:
public void searchCourses(){ Map<String,Object> map = new HashMap<String,Object>(); map.put("tutorId", 1); map.put("courseName", "%Java%"); map.put("startDate", new Date()); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); List<Course> courses = mapper.searchCourses(map); for (Course course : courses){ System.out.println(course); } }此处将生成查询语句SELECT * FROM COURSES WHERE TUTOR_ID= ? AND NAME like ? AND START_DATE >= ?。
3.6.2 choose,when 和 otherwise 条件
有时候,查询功能是以查询类别为基础的。首先,用户需要先选择是否希望通过选择讲师,课程名称,开始时间,或结束时间作为查询条件类别来进行查询,然后根据选择的查询类别,输入相应的参数。在这样的情景中,我们【需要只使用其中一种】查询类别。
MyBatis提供了<choose>元素支持此类型的SQL预处理。
如果没有选择查询类别,则查询开始时间在今天之后的课程,代码如下:
注意:mysql中now()是当前时间 oracle需要使用sysdate
<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>MyBatis计算<choose>测试条件的值,且使用第一个值为TRUE的子句。如果没有条件为 true,则使用<otherwise>内的子句。
相当于我们常用的java代码中的这个例子:
if(){
..
}
else if(){
..
}
else{
..
}
测试代码:
map.put("tutorId", 1); map.put("courseName", "%Java%"); map.put("startDate", new Date()); map.put("searchBy","CourseName");//和when中CourseName对应3.6.3 Where 条件
有时候,所有的查询条件应该是可选的。在需要使用至少一种查询条件的情况下,我们应该使用WHERE子句。并且如果有多个条件,我们需要在条件中添加AND或OR。
MyBatis提供了<where>元素支持这种类型的动态SQL语句。
在我们查询课程界面,我们假设所有的查询条件是可选的。进而,当需要提供一个或多个查询条件时,应该改使用WHERE子句。
<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> <if test="endDate != null"> AND end_date <![CDATA[ <= ]]> #{endDate} </if> </where> </select><where>元素只有在其内部标签有返回内容时才会在动态语句上插入WHERE条件语句。并且,如果WHERE子句以AND或者OR打头,则打头的AND或OR将会被移除。例如:如果参数tutorId的值为null,并且courseName参数值不为null,则<where>标签会将AND name like #{courseName}中的AND移除掉,生成的SQL WHERE子句为:
where name like #{courseName}
3.6.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语句
suffix表示后缀,和prefix相反
suffixOverrides="and"表示如果最后生成的sql语句多一个and,则自动去掉.
prefixOverrides的意思是处理前缀,和suffixOverrides相反
这里如果任意一个<if>条件为true,<trim>元素会插入WHERE,并且移除紧跟WHERE后面的AND
3.6.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> <foreach item="tutorId" collection="tutorIds"> OR tutor_id=#{tutorId} </foreach> </where> </if> </select>代码:
接口:
public interface DynamicSqlMapper{ 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); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.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="tempValue" collection="tutorIds" open="(" separator="," close=")"> #{tempValue} </foreach> </where> </if> </select>3.6.6 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}
0 0
- Mybatis中动态SQL
- MyBatis中动态SQL
- MyBatis中动态SQL语句的书写
- Mybatis下动态sql中##和$$区别
- mybatis中动态sql常用的标签
- mybatis中动态sql常用的标签
- mybatis中动态sql常用的标签
- mybatis框架中动态sql的应用
- mybatis中动态sql的使用
- mybatis中动态sql常用的标签
- MyBatis动态sql中模糊查询
- MyBatis动态SQL中trim的使用
- Mybatis中动态sql(多条件查询)
- ssm框架学习---mybatis中动态sql中的sql片段
- mybatis动态SQL语句
- MyBatis动态SQL
- MyBatis 动态SQL
- Mybatis 动态SQL
- Mybatis中一对多映射详解
- 扎实java基础
- Mybatis中多对多映射详解
- Android Studio像普通软件一样更新
- QT 5.7 QWebEngineView加载网页卡的解决方法
- Mybatis中动态SQL
- JavaScript prototype
- Android跨进程通信的四种方式
- [LeetCode] 390. Elimination Game
- it自学网站推荐
- mybatis的一些特殊功能
- ORACLE逐行累计求和方法(OVER函数)
- linux文件操作
- ZeroMQ(java)之Requerst/Response模式