1. 动态sql语句
1.1 动态sql语句概述
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。
参考的官方文档,描述如下:
官网地址:https://mybatis.org/mybatis-3/zh/dynamic-sql.html
1.2 动态 SQL之 if标签
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
如下图:
<select id="findByCondition" parameterType="student" resultType="student"> select * from student <where> <if test="id!=0"> and id=#{id} </if> <if test="username!=null"> and username=#{username} </if> </where> </select>
当查询条件id和username都存在时,控制台打印的sql语句如下:
//获得MyBatis框架生成的StudentMapper接口的实现类 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student condition = new Student(); condition.setId(1); condition.setUsername("lucy"); Student student = mapper.findByCondition(condition);
当查询条件只有id存在时,控制台打印的sql语句如下:
//获得MyBatis框架生成的UserMapper接口的实现类 StudentMapper mapper = sqlSession.getMapper( StudentMapper.class); Student condition = new Student(); condition.setId(1); Student student = mapper.findByCondition(condition);
总结语法:
<where>:条件标签。如果有动态条件,则使用该标签代替 where 关键字。 <if>:条件判断标签。 <if test=“条件判断”> 查询条件拼接 </if> </where>
1.3 动态 SQL之 foreach标签
循环执行sql的拼接操作,例如:SELECT * FROM student WHERE id IN (1,2,5)。
<select id="findByIds" parameterType="list" resultType="student"> select * from student <where> <foreach collection="array" open="id in(" close=")" item="id" separator=","> #{id} </foreach> </where> </select>
测试代码片段如下:
//获得MyBatis框架生成的UserMapper接口的实现类 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); int[] ids = new int[]{2,5}; List<Student> sList = mapper.findByIds(ids); System.out.println(sList);
总结语法:
<foreach>:循环遍历标签。适用于多个参数或者的关系。 <foreach collection=“”open=“”close=“”item=“”separator=“”> 获取参数 </foreach>
参数说明
1.4 SQL片段抽取 sql标签
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
<!--抽取sql片段简化编写--> <sql id="selectStudent" >SELECT * FROM student</sql> <select id="findById" parameterType="int" resultType="student"> <include refid="selectStudent"></include> where id=#{id} </select> <select id="findByIds" parameterType="list" resultType="student"> <include refid="selectStudent"></include> <where> <foreach collection="array" open="id in(" close=")" item="id" separator=","> #{id} </foreach> </where> </select>
总结语法:
我们可以将一些重复性的 SQL 语句进行抽取,以达到复用的效果。
<sql>:抽取 SQL 语句标签。 <include>:引入 SQL 片段标签。 <sql id=“片段唯一标识”>抽取的 SQL 语句</sql> <include refid=“片段唯一标识”/>
1.5 动态sql之 choose标签
<select id="selectConditionWhen" resultType="student" parameterType="student"> <include refid="select"/> <where> <choose> <when test="id != null"> id = #{id} </when> <when test="name != null"> AND name = #{name} </when> <when test="age != null"> AND age = #{age} </when> <otherwise></otherwise> </choose> </where> </select>
测试代码如下:
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student stu =new Student(); stu.setId(2); List<Student> list = mapper.selectCondition(stu); for (Student student : list) { System.out.println(student); } sqlSession.close(); inputStream.close();
choose会实现如下功能:
- 多个 when 标签中,只能执行一个。也就是说:当一个 when 条件满足并执行后,其它的 when 将不再执行。
- 当所有 when 都不满足条件时,执行 otherwise 标签。
if 与 choose 的区别:if 相当于java中的if语句; choose相当于java中的switch语句。
1.6 trim标签
trim标签可以在自己包含的内容中加上某些前缀或后缀,与之对应的属性是:prefix、suffix。 还可以把包含内容的开始内容覆盖,即忽略。也可以把结束的某些内容覆盖,对应的属性是:prefixOverrides、suffixOverrides
<insert id="insertTrim" parameterType="student"> insert into student <trim prefix="values(" suffix=")" suffixOverrides=","> <if test="id!=null and id!=''"> id, </if> <if test="name!=null and name!=''"> name, </if> <if test="age!=null and age!=''"> age, </if> </trim> </insert>
@Test public void InsertTrim() throws Exception { InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student stu = new Student(); stu.setId(2); stu.setName("taoge"); stu.setAge(18); int num = mapper.insertTrim(stu); sqlSession.close(); inputStream.close(); }
注意:
- prefix与suffix可以在sql语句中拼接出一对小括号。
- suffixOberrides可以将最后一个逗号去掉。