目录

一、什么是动态SQL

二、动态sql环境搭建

三、if标签

三、where标签

四、foreach 循环标签


一、什么是动态SQL

动态SQL是一种在运行时根据条件动态生成SQL语句的技术。它允许根据不同的情况构建不同的SQL查询,简单的说就是根据查询条件的不同,生成不同的SQL。

如果有一些业务比较复杂的功能,往往需要拼接SQL,而拼接SQL一不注意,少了引号,空格等格式问题,可能导致错误。为了解决这方面问题,MyBatis使用了动态SQL,通过if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高SQL语句的准确性的同时,也大大提高了开发人员的效率。
 

二、动态sql环境搭建

1.首先创建一个名为user的数据库表。

CREATE TABLE `user` (
`id` varchar(50) NOT NULL COMMENT '用户id',
`user_name` varchar(100) NOT NULL COMMENT '用户名称',
`sex` varchar(3) NOT NULL COMMENT '性别',
`create_date` datetime NOT NULL COMMENT '创建时间',
`age` int(30) NOT NULL COMMENT '年龄'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

2.在项目中创建相对于的实体类

package com.myBatisDemo.pojo;

import lombok.Data;
import java.util.Date;
//实体类
//使用Lombok自动生成无参构造函数和setter/getter、equals、canEqual、hashCode、toString方法
@Data
public class Blog {
    private String id;
    private String userName;
    private String sex;
    private Date createDate;
    private int age;
}

3.之后再持久层创建对应的Mapper接口,用于编写操作数据库的方法

package com.MyBatisDemo.dao;

import com.atangbiji.pojo.Blog;

public interface UserMapper{
    //新增一个博客
    int addUSer (User user);
}

4.再项目的resources下创建映射器的配置文件UserMapper.xml,再配置文件中使用标签实现动态SQL语句和映射器函数接口的映射关系。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间(绑定对应的映射器接口)-->
<mapper namespace="com.myBatisDemo.dao.UserMapper">
    <insert id="addUser" parameterType="User">
        insert into User(id, user_name, age, create_date, sex)
        values (#{id},#{userName},#{age},#{createDate},#{sex});
    </insert>
</mapper>

5.之后再项目的test/java目录下测试代码。

import com.atangbiji.pojo.Blog;
import com.atangbiji.utils.IDUtil;
import com.atangbiji.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.Date;

public class MapperTest {
    @Test
    public void addInitUSer(){
        //1、从SqlSessionFactory中获取SqlSession对象
        try(SqlSession sqlSession = MyBatisUtils.getSqlSession()){
            //2、执行SQL语句
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

            Blog blog = new Blog();
            blog.setId(IDUtil.generateId());
            blog.setUserName("张三");
            blog.SetGae(20);
            blog.setCreateDate(new Date());
            blog.setSex("男");
            mapper.addUser(blog);

            //3、手动提交事务
            sqlSession.commit();
        }
    }
}

三、if标签

语法格式:

<if test="boolean判断结果"> <!--要么为true、要么为false--> 
    sql语句的部分 
</if>
<!-- 对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段断拼接到其所在的 SQL 语句中。-->

应用实例:

import com.bjpowernode.entity.Student;
 
import java.util.List;
 
/**
 *
 */
public interface StudentDao {
 
    //if
    List<Student> selectIf(Student student);
 
}
<!-- if
     test: 使用对象的属性值作为条件
-->
<select id="selectIf" resultType="com.bjpowernode.entity.Student">
     select *
     from student
     where id=-1
     <if test="name!=null and name!=''">
         or name=#{name}
     </if>
 
     <if test="age>0">
         or age=#{age}
     </if>
</select>
<!--
    <if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 id=-1的子句。
    因为,若 where 后的所有<if/>条件均为 false,而 where 后若又没有 id=-1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。
    所以,在where 后,需要添加子句 id=-1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
-->
@Test
    public void testSelectIf() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        Student student=new Student();
        student.setName("王昭君");
        student.setAge(20);
        List<Student> students=studentDao.selectIf(student);
        students.forEach( stu -> System.out.println("stu === " + stu) );
        session.close();
    }

上述测试代码执行后的sql语句为:

select *
from student
where id=-1 or name="张起灵" or age=20

MyBatis 动态sql必须要掌握的标签你知道吗_List

三、where标签

语法格式:

<where> 
    其他动态sql 
</where>

应用实例:

<!-- where -->
    <select id="selectWhere" resultType="com.bjpowernode.entity.Student">
        select *
        from student
        <where>
            <if test="name!=null and name!=''">
                or name=#{name}
            </if>
 
            <if test="age>0">
                or age=#{age}
            </if>
        </where>
    </select>
 
<!--
    使用<where/>标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。
    需要注意的是,第一个<if/>标签中的SQL 片断,可以不包含 and。不过,写上 and 也不错,where标签会将离它最近的 and 或者 or 删掉。
    但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
-->
@Test
    public void testSelectWhere() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        Student student=new Student();
        student.setName("张三");
        student.setAge(20);
        List<Student> students=studentDao.selectWhere(student);
        students.forEach( stu -> System.out.println("stu === " + stu) );
        session.close();
    }

经过这次添加where标签后,测试代码之后的sql为;

select *
from student
where id=-1 or name="张起灵" or age=20

MyBatis 动态sql必须要掌握的标签你知道吗_sql_02

四、foreach 循环标签

语法格式:

<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
    #{item的值}
</foreach>
 
<!--
    如果dao接口中方法的形参是数组,则collection="array"
    如果dao接口中方法的形参是List,则collection="list"
    #item的值}:获取集合成员的值
-->

应用实例: 

import com.bjpowernode.entity.Student;
 
import java.util.List;
 
/**
 *
 */
public interface StudentDao {
 
    //for-each 1
    List<Student> selectForeachOne(List<Integer> idlist);
 
}
<!-- foreach第一种方式,循环简单类型的List: List<Integer> -->
    <select id="selectForeachOne" resultType="com.bjpowernode.entity.Student">
        select *
        from student
        <if test="list!=null and list.size>0">
            where id in
            <foreach collection="list" open="(" close=")" separator="," item="stuid">
                #{stuid}
            </foreach>
        </if>
    </select>
@Test
    public void testSelectForeachOne() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        List<Integer> idlist=new ArrayList<>();
        idlist.add(1001);
        idlist.add(1002);
        idlist.add(1003);
        List<Student> students=studentDao.selectForeachOne(idlist);
        students.forEach( stu -> System.out.println("stu === " + stu));
        session.close();
    }

添加foreach标签后,测试代码之后的sql为;

select *
from student
where id in (1001,1002,1003)

MyBatis 动态sql必须要掌握的标签你知道吗_sql_03

在开发过程中,比较常用的动态SQL标签的格式为:

<sql id="...">
    sql语句
</sql>
 
<include refid="sql标签的id属性值"></include>
 
<!--
    <sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。
    而其它标签使用该 SQL 片断,需要使用<include/>子标签。
    该<sql/>标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL 的任何位置。
-->

应用实例

import java.util.List;
 
/**
 *
 */
public interface StudentDao {
 
    //代码片段
    List<Student> selectSql(List<Student> studentList);
}
<!-- 定义代码片段 -->
    <sql id="selectStudent">
        select id,name,age from student
    </sql>
    <sql id="studentFieldList">
        where id in
    </sql>
    <select id="selectSql" resultType="com.bjpowernode.entity.Student">
        <include refid="selectStudent"></include>
        <if test="list!=null and list.size>0">
            <include refid="studentFieldList"></include>
            <foreach collection="list" open="(" close=")" separator="," item="student">
                #{student.id}
            </foreach>
        </if>
    </select>
@Test
    public void testSelectSql() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        List<Student> list=new ArrayList<>();
        Student s1=new Student();
        s1.setId(1001);
        Student s2=new Student();
        s2.setId(1002);
        Student s3=new Student();
        s3.setId(1003);
        list.add(s1);
        list.add(s2);
        list.add(s3);
        List<Student> students=studentDao.selectSql(list);
        students.forEach( stu-> System.out.println("stu === " + stu));
        session.close();
    }

上述测试代码执行后:

select id,name,age
from student
where id in (1001,1002,1003)

MyBatis 动态sql必须要掌握的标签你知道吗_List_04

  注:喜欢的朋友可以关注公众号“JAVA学习课堂”方便阅读,内容同步更新。

MyBatis 动态sql必须要掌握的标签你知道吗_sql_05