MyBatis 框架动态 SQL
内容列表
◼ 动态 SQL-if
◼ 动态 SQL-where
◼ 动态 SQL-foreach
◼ 动态 SQL-片段
动态 SQL,通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句。这里的条件判
断使用的表达式为 OGNL 表达式。常用的动态 SQL 标签有 、 、 、 等。
MyBatis 的动态 SQL 语句,与 JSTL 中的语句非常相似。
动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行
查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行
排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题
环境准备
创建新的 maven 项目,加入 mybatis , mysql 驱动依赖
创建实体类 Student , StudentDao 接口,StudentDao.xml , mybatis.xml , 测试类
使用之前的表 student。
在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。特别是对于小于号(<),在 XML 中是绝不能出现的。否则解析 mapper 文件会出错。
实体符号表:
项目结构目录如下:
1. 2 动态 SQL 之
接口方法:
List<Student> selectStudentIf(Student student);
mapper 文件:
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
where 1=1
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="age > 0 ">
and age > #{age}
</if>
</select>
测试方法:
@Test
public void testSelectStudentIf(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
// student.setName("李四");
// student.setAge(18);
student.setName("李四");
student.setAge(20);
List<Student> students = dao.selectStudentIf(student);
for(Student stu:students){
System.out.println("if==="+stu);
}
}
2.动态 SQL 之
标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后
的所有 条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL
出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会
严重影响查询效率。
使用 标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加
where 子句。需要注意的是,第一个 标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,
系统会将多出的 and 去掉。但其它 中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
。
语法: 其他动态 sql
接口方法:
List<Student> selectStudentWhere(Student student);
mapper文件:
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
<where>
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="age > 0 ">
and age > #{age}
</if>
</where>
</select>
测试方法:
@Test
public void testSelectWhere() throws IOException {
Student param = new Student();
param.setName("李力");
param.setAge(18);
List<Student> studentList = studentDao.selectStudentWhere(param);
studentList.forEach( stu -> System.out.println(stu));
}
结果如下:
3. 动态 SQL 之
标签用于实现对于数组与集合的遍历。对其使用,需要注意:
➢ collection 表示要遍历的集合类型, list ,array 等。
➢ open、close、separator 为对遍历内容的 SQL 拼接。
语法:
<foreach collection="集合类型" open="开始的字符" close="结束的字符"
item="集合中的成员" separator="集合成员之间的分隔符">
#{item 的值}
</foreach>
-
遍历 List< 简单类型 >
表达式中的 List 使用 list 表示,其大小使用 list.size 表示。
需求:查询学生 id 是 1002,1005,1006
接口方法:
List<Student> selectStudentForList(List<Integer> idList);
mapper文件
<!--foreach使用1 , List<Integer>--> <select id="selectForeachOne" resultType="com.bjpowernode.domain.Student"> select * from student where id in <foreach collection="list" item="myid" open="(" close=")" separator=","> #{myid} </foreach> </select>
测试方法:
@Test public void testSelectForEach(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); List<Integer> list = new ArrayList<>(); list.add(1001); list.add(1002); list.add(1003); List<Student> students = dao.selectForeachOne(list); for(Student stu:students){ System.out.println("foreach--one ==="+stu); } }
测试结果如下:
-
遍历 List< 对象类型 >
在Dao中添加方法
List<Student> selectStudentForList2(List<Student> stuList);
编写mapper文件
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student"> <include refid="studentSql" /> where id in ( <foreach collection="list" item="stu" > #{stu.id}, </foreach> -1 ) </select>
测试方法如下:
4.动态 SQL 之代码片段
标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用
子标签。该 标签可以定义 SQL 语句中的任何部分,所以 子标签可以放在动态 SQL
的任何位置。
定义一个代码片段:
<!--定义sql片段-->
<sql id="studentSql">
select id,name, age, email from student
</sql>
<sql id="studentSqlOne">
id,name, age, email
</sql>
使用代码片段:
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
select <include refid="studentSqlOne" /> from student
where id > 0
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
<!--
where: <where> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql" />
<where>
<if test="name !=null and name !='' ">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>