在一些情况下,如查询参数不确定时,需要用到动态sql
例子,根据动态输入的查询条件查询student.
一.if语句
1.StudentTMapper
[html] view plain copy
- package com.skymr.mybatis.mappers;
- import java.util.List;
- import java.util.Map;
- import com.skymr.mybatis.model.Student;
- public interface StudentTMapper {
- public List<Student> searchStudents(Map<String,Object> map);
- }
map参数是查询条件
2.StudentTMappler.xml
[html] view plain copy
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <!-- namespace:Mapper映射 -->
- <!-- 这个文件感觉就像StudentMapper接口的实现一样,只是从java文件变成了xml文件
- 充当了Dao类的功能
- -->
- <mapper namespace="com.skymr.mybatis.mappers.StudentTMapper">
- <resultMap type="Student" id="stuMap">
- <id property="id" column="id"/>
- <result property="name" column="name"/>
- <result property="age" column="age"/>
- <association property="address" column="address_id" select="com.skymr.mybatis.mappers.AddressMapper.getAddress">
- </association>
- <association property="grade" column="grade_id" select="com.skymr.mybatis.mappers.GradeMapper.getGrade"></association>
- </resultMap>
- <select id="searchStudents" resultMap="stuMap" parameterType="map">
- select * from mybatis_student where 1=1
- <if test="name!=null">
- and name like #{name}
- </if>
- <if test="age!=null">
- and age=#{age}
- </if>
- </select>
- </mapper>
3.测试
[html] view plain copy
- package com.skymr.mybatis.service;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import com.skymr.mybatis.mappers.StudentTMapper;
- import com.skymr.mybatis.model.Student;
- import com.skymr.mybatis.util.MybatisUtil;
- public class StudentTest4 {
- private Logger logger = LoggerFactory.getLogger(StudentTest4.class);
- private SqlSession session;
- @Before
- public void beforeTest(){
- session = MybatisUtil.openSession();
- }
- @After
- public void afterTest(){
- session.close();
- }
- @Test
- public void testSearch(){
- logger.info("测试查询学生");
- StudentTMapper mapper = session.getMapper(StudentTMapper.class);
- Map<String,Object> map = new HashMap<String, Object>();
- map.put("name", "%aaa%");
- map.put("age", 111);
- List<Student> list = mapper.searchStudents(map);
- logger.info(list.toString());
- }
- }
二.choose,when ,otherwise
[html] view plain copy
- Sometimes we don’t want all of the conditionals to apply, instead we want to choose only one case
- among many options. Similar to a switch statement in Java, MyBatis offers a choose element.
- Let’s use the example above, but now let’s search only on title if one is provided, then only by author
- if one is provided. If neither is provided, let’s only return featured blogs (perhaps a strategically list
- selected by administrators, instead of returning a huge meaningless list of random blogs).
有些时候我们不想所有的条件都使用到,只想在所有条件中选择一个条件.与java的switch语种相似,Mybatis提供了一个元素.让我们做个例子.
[html] view plain copy
- <select id="findActiveBlogLike"
- resultType="Blog">
- SELECT * FROM BLOG WHERE state = ‘ACTIVE’
- <choose>
- <when test="title != null">
- AND title like #{title}
- </when>
- <when test="author != null and author.name != null">
- AND author_name like #{author.name}
- </when>
- <otherwise>
- AND featured = 1
- </otherwise>
- </choose>
- </select>
上面的例子是引用Mybatis文档.
自己的例子:
[html] view plain copy
- <select id="searchStudents2" resultMap="stuMap" parameterType="map">
- select * from mybatis_student where 1=1
- <choose>
- <when test="searchBy=='name'">
- and name like #{name}
- </when>
- <when test="searchBy=='gradeId'">
- and grade_id=#{gradeId}
- </when>
- <otherwise>
- and age=#{age}
- </otherwise>
- </choose>
- </select>
三.trim, where, set元素
1.当没有条件时,有可能会生成这样的sql
[html] view plain copy
- SELECT * FROM BLOG
- WHERE
如果不在后边加入 1=1,则应该加上where标签
[html] view plain copy
- <select id="findActiveBlogLike"
- resultType="Blog">
- SELECT * FROM BLOG
- <where>
- <if test="state != null">
- state = #{state}
- </if>
- </where>
- </select>
改成这样就可以避免以上情况.
2.还有这种情况
[html] view plain copy
- SELECT * FROM BLOG
- WHERE
- AND title like ‘someTitle’
需要去年多余的and /or
[html] view plain copy
- <select id="searchStudents3" resultMap="stuMap" parameterType="map">
- select * from mybatis_student
- <trim prefix="WHERE" prefixOverrides="AND|OR">
- <if test="name!=null">
- and name like #{name}
- </if>
- <if test="age!=null">
- and age=#{age}
- </if>
- </trim>
- </select>
同样,update set语句也会出现多余的","的问题
[html] view plain copy
- <update id="updateAuthorIfNecessary">
- update Author
- <set>
- <if test="username != null">username=#{username},</if>
- <if test="password != null">password=#{password},</if>
- <if test="email != null">email=#{email},</if>
- <if test="bio != null">bio=#{bio}</if>
- </set>
- where id=#{id}
- </update>
也可以使用trim修改
[html] view plain copy
- <update id="updateAuthorIfNecessary">
- update Author
- <trim prefix="SET" suffixOverrides=",">
- <if test="username != null">username=#{username},</if>
- <if test="password != null">password=#{password},</if>
- <if test="email != null">email=#{email},</if>
- <if test="bio != null">bio=#{bio}</if>
- </trim>
- where id=#{id}
- </update>
四.foreach元素
这是一个非常有用的动态sql元素,用来遍历集合,常应用于IN语句中,例:
[html] view plain copy
- IN condition. For example:
- <select id="selectPostIn" resultType="domain.blog.Post">
- SELECT *
- FROM POST P
- WHERE ID in
- <foreach item="item" index="index" collection="list"
- open="(" separator="," close=")">
- #{item}
- </foreach>
- </select>
foreach元素非常强大,它允许你指定一个集合,声明item和index变量,在元素内部使用.生成有"开始/结尾/分隔符"的字符串,这个元素非常智能,它不会不小心添加额外的分隔符.
记住,你可以把一个List实例或者一个数组当作参数传递到MyBatis.当你这样做了,MyBatis会自动放到一个Map里.List实例会以"list"作为Key值,数组实例会以"array"作为Key值.
foreach元素的属性主要有 item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名.
index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置.
open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔 符.
close表示以什么结束.
上面的例子生成的sql相当于
SELECT *
FROM POST P
WHERE ID in (?,?,?)