【MyBatis从入门到入土】7 - 动态SQL

文章目录

    • 12 动态SQL
      • 12.1 环境搭建
      • 12.2 if
      • 12.3 where
      • 12.4 choose(when、other)
      • 12.5 foreach
      • 12.6 SQL片段

12 动态SQL

动态SQL就是可以根据条件动态地添加SQL语句

12.1 环境搭建

数据库建立测试表Blog

mysql> CREATE TABLE blog(
    -> id VARCHAR(50) NOT NULL COMMENT '博客id',
    -> title VARCHAR(100) NOT NULL COMMENT '博客标题',
    -> author VARCHAR(30) NOT NULL COMMENT '博客作者',
    -> create_time DATETIME NOT NULL COMMENT '创建时间',
    -> views INT NOT NULL COMMENT '浏览量'
    -> )ENGINE=InnoDB DEFAULT CHARSET = utf8;
Query OK, 0 rows affected, 1 warning (0.21 sec)

建立实体类Blog

public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;

插入测试数据

mysql> SELECT * FROM blog;
+----------------------------------+------------------------------+--------+---------------------+-------+
| id                               | title                        | author | create_time         | views |
+----------------------------------+------------------------------+--------+---------------------+-------+
| 1457779e8d7a4a1e80e188ee59af852f | MyBatis从入门到入土          | Cap    | 2020-07-09 20:13:33 |   100 |
| fe4d963daae8464fa12df800da731cbb | Spring从入门到入土           | Cap    | 2020-07-09 20:21:01 | 20000 |
| ec89d3fb78f84f4b8179bb03c9761b59 | SpringMVC从入门到入土        | Cap    | 2020-07-09 20:21:01 |     5 |
| 03679b21b7434cefa4a8c05369965c0f | SpringBoot从入门到入土       | Cap    | 2020-07-09 20:21:01 | 99999 |
+----------------------------------+------------------------------+--------+---------------------+-------+
4 rows in set (0.02 sec)

12.2 if

if结构为:


	 

  • 在接口BlogMapping接口添加一个测试if的方法
public interface BlogMapping {
    List<Blog> queryBlogIF(Map map);
}
  • 编写动态SQL语句
    <select id="queryBlogIF" resultType="blog" parameterType="map">
        SELECT *
        FROM blog
        WHERE 1 = 1
        <if test=" title != null ">
            AND title = #{title}
        if>
    select>
  • 测试方法
    @org.junit.Test
    public void test1(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession(true);
        BlogMapping mapper = sqlSession.getMapper(BlogMapping.class);
        Map map = new HashMap();
        List<Blog> blogs = mapper.queryBlogIF(map);
        for(Blog blog : blogs){
            System.out.println(blog);
        }
    }

这里我们没有传入title,所以条件不成立,日志输出为:

Preparing: SELECT * FROM blog WHERE 1 = 1

当我们传入title的时候

    map.put("title","MyBatis从入门到入土");

日志输出:

==>  Preparing: SELECT * FROM blog WHERE 1 = 1 AND title = ?

可以看到条件成立,它将SQL语句拼接上去

12.3 where

在上一小节中,我们使用where 1 = 1来避免动态SQL拼接的问题,其实MyBatis有一个更好的解决方案,那就是使用where元素
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。(比如动态SQL语句拼接后为 WHERE AND title = ? ,where元素会将其变成WHERE title = ?
改造一下:

    <select id="queryBlogIF" resultType="blog" parameterType="map">
        SELECT *
        FROM blog
        <where>
            <if test=" title != null ">
                AND title = #{title}
            if>
        where>
    select>

12.4 choose(when、other)

choose元素会顺序选择一个条件成立的when元素,如果没有的话会从other元素中去取(如果有other元素的话)
choose的格式为:

<choose>
	<when test="expr1">
	when>
	<when test="expr1">
	when>
choose>
在接口`BlogMapping`接口添加一个测试`choose`的方法
```java
    List<Blog> queryBlogChoose(Map map);
  • 编写动态SQL语句
<select id="queryBlogChoose" resultType="blog" parameterType="map">
    SELECT *
    FROM blog
    <where>
        <choose>
            <when test="title != null">
                title = #{title}
            when>

            <when test="author != null">
                AND author = #{author}
            when>

            <otherwise>
                AND views = #{views}
            otherwise>

        choose>
    where>
select>

12.5 foreach

我们在构建IN条件语句的时候,传入的值是不确定的,通过foreach可以循环遍历一个集合来遍历传入IN条件语句的值。

  • 为了方便测试,我们修改一下blogid字段
mysql> SELECT * FROM blog;
+----+------------------------------+--------+---------------------+-------+
| id | title                        | author | create_time         | views |
+----+------------------------------+--------+---------------------+-------+
| 1  | MyBatis从入门到入土          | Cap    | 2020-07-09 20:13:33 |   100 |
| 2  | Spring从入门到入土           | Cap    | 2020-07-09 20:21:01 | 20000 |
| 3  | SpringMVC从入门到入土        | Cap    | 2020-07-09 20:21:01 |     5 |
| 4  | SpringBoot从入门到入土       | Cap    | 2020-07-09 20:21:01 | 99999 |
+----+------------------------------+--------+---------------------+-------+
4 rows in set (0.00 sec)
  • 在BlogMapping接口添加方法
List<Blog> queryBlogForeach(List<String> list);
  • 编写动态SQL语句
    <select id="queryBlogForeach" resultType="blog" parameterType="list">
        SELECT *
        FROM blog
        WHERE id IN
        <foreach collection="list" index="index" item="item"
                 open="(" separator="," close=")">
            #{item}
        foreach>
    select>
  • collection:传入的可迭代的对象
  • index:当前迭代的序号
  • item:当前迭代获得的值,当item是一个对象时,可以通过#{item.property}来取到对象的属性值

indexitem是用来在动态SQL语句中使用的

  • 编写测试方法
    @org.junit.Test
    public void test3(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapping mapper = sqlSession.getMapper(BlogMapping.class);

        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");

        mapper.queryBlogForeach(list);

        sqlSession.close();
    }

运行得到

==>  Preparing: SELECT * FROM blog WHERE id IN ( ? , ? , ? )
==> Parameters: 1(String), 2(String), 3(String)
<==    Columns: id, title, author, create_time, views
<==        Row: 1, MyBatis从入门到入土, Cap, 2020-07-09 20:13:33, 100
<==        Row: 2, Spring从入门到入土, Cap, 2020-07-09 20:21:01, 20000
<==        Row: 3, SpringMVC从入门到入土, Cap, 2020-07-09 20:21:01, 5
<==      Total: 3

12.6 SQL片段

SQL片段用于复用动态SQL代码
SQL片段的格式如下:

<sql id="sqlid_name">
	
sql>

引用时:

<include refid="sqlid_name" />

例子,假设我们原先queryBlogIF动态SQL语句为

    <select id="queryBlogIF" resultType="blog" parameterType="map">
        SELECT *
        FROM blog
        <where>
            <if test=" title != null ">
                AND title = #{title}
            if>

            <if test=" author != null" >
                AND author = #{author}
            if>
        where>
    select>

现在我们抽取if

    <sql id="if-title-author" >
        <if test=" title != null ">
            AND title = #{title}
        </if>

        <if test=" author != null" >
            AND author = #{author}
        </if>
    </sql>

再修改queryBlogIF

    <select id="queryBlogIF" resultType="blog" parameterType="map">
        SELECT *
        FROM blog
        <where>
            <include refid="if-title-author" />
        where>
    select>

现在除了queryBlogIF能够使用外,其他地方也能够引用
这样就实现了SQL片段的复用。

你可能感兴趣的:(#,Mybatis从入门到入土)