深入理解MyBatis中的动态SQL语句

有时候,静态的SQL语句并不能满足应用程序的需求。我们可以根据一些条件,来动态地构建 SQL语句。

例如,在Web应用程序中,有可能有一些搜索界面,需要输入一个或多个选项,然后根据这些已选择的条件去执行检索操作。我们可能需要根据用户选择的条件来构建动态的SQL语句。如果用户提供了任何一个条件,我们需要将那个条件添加到SQL语句的WHERE子句中。

!以下内容基于自己建的表和类!

1.<if>标签被用来通过条件嵌入SQL片段,如果条件为true,则相应地SQL片段将会被添加到SQL语句中。
 例如:
 假定有一个课程搜索界面,设置了讲师(Tutor)下拉列表框,课程名称(CourseName)文本输入框,开始时间(StartDate)输入框,结束时间(EndDate)输入框,作为搜索条件。假定课讲师下拉列表是必须选的,其他的都是可选的。当用户点击搜索按钮时,需要显示符合条件的列表数据。

对应的sql映射文件,如下所示:

<!-- 独立的Course封装映射 -->
<resultMap type="Course">
<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 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 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>内的子句。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/78289c978f48d0d3ff5fc2380f67256d.html