后台(41)——MyBatis的动态SQL-阿里云开发者社区

开发者社区> 数据库> 正文

后台(41)——MyBatis的动态SQL

简介: 探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 Android多分...

探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制


Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南


自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理


版权声明


MyBatis可利用动态SQL极大的简化SQL语句的拼接。

在此介绍几种MyBatis中常用的动态SQL

where和if

还记得我们之前有一个查询学生的例子么?

<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
        SELECT * FROM student WHERE gender=#{studentCustom.gender} and name like '%${studentCustom.name}%'
</select>

猛地一看这个SQL没啥问题,但是仔细一想又不对,studentCustom有没有可能为null呢?studentCustom.gender和studentCustom.name有没有可能为null呢?当然是有的,那么我们可以怎么处理一下呢?此时就可以用<where>和<if>,请看:

<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
        SELECT * FROM student
        <where>
            <if test="studentCustom!=null">
                <if test="studentCustom.gender!=null">
                    and gender=#{studentCustom.gender}
                </if>
                <if test="studentCustom.name!=null">
                    and name like '%${studentCustom.name}%'
                </if>
            </if>
        </where>
</select>

在此利用标签<where>和<if>对应了某些查询条件为null的情况。有人或许有疑问,如果两个查询条件都满足的话在这个sql中岂不是有两个and了?甭担心,这种情形下MyBatis会自动删除掉掉第一个and

sql

其实,我们还可以把刚才这个例子继续优化一下利用<sql>提取出<if>作为sql片段从而提高代码的复用性

    <sql id="findStudentList_if">
        <if test="studentCustom!=null">
            <if test="studentCustom.gender!=null">
                and gender=#{studentCustom.gender}
            </if>
            <if test="studentCustom.name!=null">
                and name like '%${studentCustom.name}%'
            </if>
        </if>
    </sql>

然后在查询语句中引用该sql片段即可

<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
        SELECT * FROM student
        <where>
            <include refid="findStudentList_if"></include>
        </where>
</select>

foreach

来看一种需求:查询出id为2、4、7的学生信息,我们可以这么写sql

SELECT * FROM student WHERE (id=2 OR id=4 OR id=7)

那么这个sql在MyBatis里又该怎么写呢?
在此可采用<foreach>标签来拼装这个条件(id=2 OR id=4 OR id=7)

首先,我们在StudentQueryVO中定义一个字段idsList用于传递这几个id值

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

import java.util.List;

//自定义的包装类型的pojo
public class StudentQueryVO {

    private List<Integer> idsList;

    //用户查询条件
    private StudentCustom studentCustom;

    public StudentCustom getStudentCustom() {
        return studentCustom;
    }

    public void setStudentCustom(StudentCustom studentCustom) {
        this.studentCustom = studentCustom;
    }

    public List<Integer> getIdsList() {
        return idsList;
    }

    public void setIdsList(List<Integer> idsList) {
        this.idsList = idsList;
    }

    //其他查询条件,比如教师,课程,学校等等
}

再来看mapper.xml

<sql id="findStudentList_ids_if">
        <if test="idsList!=null">
            <foreach collection="idsList" item="student_id" open="(" close=")" separator="OR">
                id=#{student_id}
            </foreach>
        </if>
</sql>

<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
    SELECT * FROM student
    <where>
        <include refid="findStudentList_ids_if"></include>
    </where>
</select>

重点来看这个<foreach>标签

  • collection表示pojo中的集合
  • item表示遍历时集合中每个元素
  • open表示组拼后的语句的开头
  • close表示组拼后的语句的结尾
  • separator表示每个部门的连接符

最后来看测试代码

@Test
    public void findStudentList() throws IOException {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        StudentQueryVO studentQueryVO=new StudentQueryVO();
        List<Integer> idsList=new ArrayList<Integer>();
        idsList.add(2);
        idsList.add(4);
        idsList.add(7);
        studentQueryVO.setIdsList(idsList);
        List<StudentCustom> studentList = studentMapper.findStudentList(studentQueryVO);
        for (int i = 0; i <studentList.size(); i++) {
            StudentCustom sc = studentList.get(i);
            System.out.println(sc);
        }
        sqlSession.commit();
        sqlSession.close();
    }

其实,这些动态SQL并不难,也不需要死记硬背。但是要把握住总的原则和目标:利用动态SQL拼装成原始的sql语句。在实际开发时也可以先写出原始sql语句再写到mapper.xml中

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章