MyBatis学习(三)MyBatis的动态SQL

动态SQL
1、动态Sql简介

Mybatis官方文档

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
2、使用动态SQL开发

数据库:

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(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

数据表对应的实体类:

package com.zyh.pojo;

import lombok.Data;

import java.util.Date;
@Data
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createime;
    private int views;
}

实体类对应的接口:

package com.zyh.mapping;

import com.zyh.pojo.Blog;

public interface BlogMapper {

    /**
     * 插入数据
     * @param blog
     * @return
     */
    int addBlog(Blog blog);

}

接口的BlogMapper.xml配置

<?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 namespace="com.zyh.mapping.BlogMapper">
<!--添加博客-->
<insert id="addBlog" parameterType="Blog">
        insert into mybatis.blog(id,title,author,create_time,views)
        <!-- #{}大括号里面的取值都是实体类中的属性,所以必须要保证和实体类属性名一致-->
        values (#{id},#{title},#{author},#{createTime},#{views});
    </insert>
</mapper>

测试:新增博客

package com.zyh.mapping;

import com.zyh.pojo.Blog;
import com.zyh.utils.IDUtils;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.Date;


public class BlogMapperTest {
    @Test
    public void test(){
        SqlSession session = MyBatisUtils.getSession(true);
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        //新增博客
        for (int i = 1; i <= 10; i++) {
            Blog blog = new Blog();
            blog.setId(IDUtils.getId());
            blog.setTitle("Mybatis"+i);
            blog.setAuthor("zyh");
            blog.setCreateTime(new Date());
            blog.setViews(399);
            mapper.addBlog(blog);
        }

        session.close();

    }
}

执行结果:
在这里插入图片描述

在这里插入图片描述
案例1:if

通过作者名字和博客名字来查询博客
如果作者的名字为空,就根据博客名字来查询

接口新增方法:

package com.zyh.mapping;

import com.zyh.pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {

    /**
     * 插入数据
     */
    int addBlog(Blog blog);

    /**
     * > 通过作者名字和博客名字来查询博客
     * > 如果作者的名字为空,就根据博客名字来查询
     *  如果不知道参数有几个,就使用Map进行传参
     */
     List<Blog> getBlogByIf(Map map);
}

BlogMapper.xml 中的新增配置:

<select id="getBlogByIf" parameterType="map" resultType="Blog">
          select * from mybatis.blog where
          <if test="title!=null">
              title=#{title}
          </if>
          <if test="author!=null">
              and author=#{author}
          </if>
    </select>

测试:

    @Test
    public void testgetBlogByIf(){
        SqlSession session = MyBatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String, String> map = new HashMap<String, String>();
        map.put("title","Mybatis1");
        map.put("author","zyh");
        List<Blog> blogs = mapper.getBlogByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

执行结果:
在这里插入图片描述
案例2:where 如果测试时给这个方法传递的参数是一个空 map ,会发生什么呢?

测试:

    @Test
    public void testgetBlogByIf(){
        SqlSession session = MyBatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String, String> map = new HashMap<String, String>();
//        map.put("title","Mybatis1");
//        map.put("author","zyh");
        List<Blog> blogs = mapper.getBlogByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }
}

在这里插入图片描述
我们可以看到 Sql 语句报错,SQL: select * from mybatis.blog where ,如果参数为空,后面的where语句的条件就为空,所以报错。

解决办法:where判断条件时可以使用动态SQL 标签,如果后面的条件为空,就可以自动去掉这个 where,而且在where 标签中,如果where后的条件是以or 或 and 开头,会自动去掉这个关键字。

xml中的sql语句:

select id="getBlogByIf" parameterType="map" resultType="Blog">
          select * from mybatis.blog
        <where>
            <if test="title!=null">
                title=#{title}
            </if>
            <if test="author!=null">
                and author=#{author}
            </if>
        </where>
    </select>

在这里插入图片描述

案例3:set 如果后面的条件满足,它就会自动拼接 set 标签,后面如果有多余的,就会自动去掉。

接口:

    /**
     * 更新博客数据
     */
    int updateBlog(Map map);

xmlSQL配置

    <update id="updateBlog" parameterType="map">
        <!--原来的语句
           update mybatis.blog
           set title=#{title},author=#{author}
           where id=#{id}
        -->
        update mybatis.blog
        <set>
            <if test="title!=null">
                title=#{title},
            </if>
            <if test="author!=null">
                author=#{author}
            </if>
        </set>
        where id=#{id}
    </update>

测试:

    @Test
    public void testUpdateBlog(){
        SqlSession session = MyBatisUtils.getSession(true);
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String,String> map = new HashMap<String, String>();
        map.put("id","33889a4a983e43cbb6a4acf47cc64a86");
        map.put("author","hang");
        map.put("title","Spring");
        mapper.updateBlog(map);

        session.close();
    }

执行结果:
在这里插入图片描述

如果我们只传递一个title参数,那么title=#{title}, 后面的逗号怎么办呢?set就可以用来处理这个问题,会自动去掉这个逗号。

测试:

    @Test
    public void testUpdateBlog(){
        SqlSession session = MyBatisUtils.getSession(true);
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String,String> map = new HashMap<String, String>();
        map.put("id","33889a4a983e43cbb6a4acf47cc64a86");
        map.put("title","SpringMVC");
        mapper.updateBlog(map);

        session.close();
    }

在这里插入图片描述

案例4: choose 类似于Java 中的Switch

接口:

 /**
     * 查询博客,只要满足一个条件即可
     */
    List<Blog> queryBlogByChoose(Map map);

xml中的SQL:

    <select id="queryBlogByChoose" parameterType="map" resultType="Blog">
        select * from  mybatis.blog
        <where>
            <choose>
                <!--when 就相当于case-->
                <when test="title!=null">
                    title=#{title}
                </when>
                <when test="author!=null">
                    and author=#{author}
                </when>

                <!--otherwise 就相当于default-->
                <otherwise>
                    and views=#{views}
                </otherwise>
            </choose>
        </where>
    </select>

测试:

第一次 :参数为空

    @Test
    public void testQueryBlogByChoose(){
        SqlSession session = MyBatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String,String> map = new HashMap<String, String>();
        List<Blog> blogs = mapper.queryBlogByChoose(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

执行结果:
在这里插入图片描述
第二次:参数为author

    @Test
    public void testQueryBlogByChoose(){
        SqlSession session = MyBatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String,String> map = new HashMap<String, String>();
        map.put("author","hang");
        List<Blog> blogs = mapper.queryBlogByChoose(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
第三次:参数为title

    @Test
    public void testQueryBlogByChoose(){
        SqlSession session = MyBatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String,String> map = new HashMap<String, String>();
        map.put("title","Mybatis3");

        List<Blog> blogs = mapper.queryBlogByChoose(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
第四次:参数为title + author

    @Test
    public void testQueryBlogByChoose(){
        SqlSession session = MyBatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String,String> map = new HashMap<String, String>();
        map.put("title","SpringMVC");
        map.put("author","hang");
        List<Blog> blogs = mapper.queryBlogByChoose(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值