Chapter4 MyBatis框架动态SQL
4.1 概述
4.1.1 什么是动态SQL
- 动态 SQL是指通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句
- 常用的动态 SQL 标签有
<if>
、<where>
、<choose/>
、<foreach>
等 - 动态 SQL,主要用于解决查询条件不确定的情况
4.1.2 环境准备
步骤
- 创建maven项目,引入mybatis、mysql驱动依赖
- 创建实体类Student、StudentDao接口、接口映射文件、mybatis配置文件
- 创建mysql数据库,新建表student
注意事项
要使用动态sql,dao接口方法的参数必须是对象
mapper 的动态 SQL 中,大于号、小于号、大于等于、小于等于等应进行转义
符号表:
符号 含义 转义符 < 小于 <
> 大于 >
>= 大于等于 >=
<= 小于等于 <=
4.2 动态SQL — if
4.2.1 if标签
- if 标签作为 select 等标签的子标签使用
- test 属性值为判断语句
4.2.2 使用实例
- 说明:
- 找到邮箱为weasley@jk.com且年龄大于12岁的学生(即Ron)
- where后面加上 1=1,这样每个if标签都可以加and或者or标签(如果第一个不加and而第一个条件不满足直接执行后面的if,就变成了
where and age > #{age}
,会报错)
- 代码
- mapper
<select id="selectStudentIf" resultType="com.powernode.domain.Student"> select * from student where 1=1 <if test="email != null and email != '' "> and email = #{email} </if> <if test="age>0"> and age > #{age} </if> </select>
- test
@Test public void testSelectLikeTwo() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); Student student = new Student(); student.setAge(12); student.setEmail("weasley@jk.com"); List<Student> students = dao.selectStudentIf(student); students.forEach(stu->System.out.println(stu)); sqlSession.close(); }
- mapper
4.3 动态SQL — <where>
说明
- 前面提到if标签需要在where后面加一个恒等条件,但当查询量很大时,会影响效率
- 使用where标签可以避免这种问题
- where标签作为if的上一级标签使用,第一个if语句可以不加and或or,但后面的要加
实例
mapper
<select id="selectStudentWhere" resultType="com.powernode.domain.Student"> select * from student <where> <if test="email != null and email != '' "> email = #{email} </if> <if test="age>0"> and age > #{age} </if> </where> </select>
test
@Test public void testSelectStudentWhere() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); Student student = new Student(); student.setAge(12); student.setEmail("weasley@jk.com"); List<Student> students = dao.selectStudentWhere(student); students.forEach(stu->System.out.println(stu)); sqlSession.close(); }
4.4 动态SQL — foreach
4.4.1 说明
foreach 标签
<foreach>
标签用于实现对于数组与集合的遍历- 语法:
<foreach collection=" " open=" " close="" item=" " separator=" ">
属性
- collect:集合类型,array或list
- open:要转换成sql语句的开始符号,如
(
- cloae:结束符号
- item:自定义,表示数组或集合的成员
- separator:分隔符
案例一:遍历简单类型的集合
- mapper
<select id="selectStudentForeachOne" resultType="com.powernode.domain.Student"> select * from student where id in <foreach collection="list" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>
- test
@Test public void testSelectStudentForeachOne() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); List<Integer> idList =new ArrayList<>(); idList.add(1001); idList.add(1002); idList.add(1003); List<Student> students = dao.selectStudentForeachOne(idList); students.forEach(stu->System.out.println(stu)); sqlSession.close(); }
- mapper
案例二:遍历对象集合
mapper
<select id="selectStudentForeachTwo" resultType="com.powernode.domain.Student"> select * from student where id in <foreach collection="list" item="stu" open="(" close=")" separator=","> #{stu.id} </foreach> </select>
test
@Test public void testSelectStudentForeachTwo() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); List<Student> student = new ArrayList<>(); Student stu = new Student(); stu.setId(1001); student.add(stu); stu = new Student(); stu.setId(1004); student.add(stu); List<Student> students = dao.selectStudentForeachTwo(student); students.forEach(s->System.out.println(s)); sqlSession.close(); }
4.5 动态SQL — 代码片段
4.5.1 说明
- 定义
<sql/>
标签用于定义 SQL 片段,以便其它 SQL 标签复用 - 使用
- 语法规则
- 创建:
<sql id=""> </sql>
- 使用:
<include refid="sql标签的id"/>
- 创建:
- 使用 SQL 片段,需要使用
<include/>
标签 <include>
子标签可以放在动态 SQL的任何位置
- 语法规则
4.5.2 示例
- mapper
<!-- 创建 --> <sql id="studentSql"> select * from student </sql> <!-- 使用 --> <select id="selectStudentForeachOne" resultType="com.powernode.domain.Student"> <include refid="studentSql"/> where id in <foreach collection="list" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>