1. 动态SQL

1.1 介绍

  • 概念:**动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句.*

    官网描述:

    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
    -------------------------------

1.2 搭建环境

  1. 新建一个表:blog

    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;
  2. 插件IDUtil工具类

    public class IDUtil {
       public static String genId(){
           return UUID.randomUUID().toString().replaceAll("-","");
      }
    }
  3. 编写实体类

    public class Blog {
       private String id;
       private String title;
       private String author;
       private Date createTime;
       private int views; // 无参构造
    // 有参构造
    // get、set、toString
    }
  4. 编写Mapper接口及mapper配置文件

    public interface BlogMapper {
    int addBlog(Blog blog);
    }
    <?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">
    <mapper namespace="top.linzeliang.mapper.BlogMapper">
    <insert id="addBlog" parameterType="blog">
    insert into blog (id, title, author, create_time, views)
    values (#{id},#{title},#{author},#{createTime},#{views});
    </insert>
    </mapper>
  5. 在MyBatis配置文件中设置下驼峰线自动转换

    <settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--注册Mapper.xml-->
    <mappers>
    <mapper resource="top/linzeliang/mapper/BlogMapper.xml"/>
    </mappers>
  6. 初始化博客方法

    @Test
    public void addInitBlog(){
    SqlSession session = MybatisUtils.getSession();
    BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = new Blog();
    blog.setId(IDUtil.genId());
    blog.setTitle("Mybatis如此简单");
    blog.setAuthor("妙啊");
    blog.setCreateTime(new Date());
    blog.setViews(9999); mapper.addBlog(blog); blog.setId(IDUtil.genId());
    blog.setTitle("Java如此简单");
    mapper.addBlog(blog); blog.setId(IDUtil.genId());
    blog.setTitle("Spring如此简单");
    mapper.addBlog(blog); blog.setId(IDUtil.genId());
    blog.setTitle("微服务如此简单");
    mapper.addBlog(blog); session.close();
    }

2. IF和WHERE语句

  • if语句就是判断是否满足某个条件,满足的话就添加标签内容到sql语句中
  • where语句:如果包含的标签中含有返回值得话,他就会自动插入一个where,如果返回值的内容的第一个开头是 and 或者 or,则会自动剔除

需求:根据作者名字和博客名字来查询博,如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询

  1. 编写接口类

    List<Blog> queryBlogIf(Map map);
  2. 编写对应的mapper配置文件

    • 传入的参数是map,那么在if标签中直接写的是map中的key,不用加#{}
    <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>

3. SET语句

  • 如果在进行更新操作的时候,含有 set 关键词,则使用set标签,效果和where也是一样的
  1. 编写接口方法

    int updateBlog(Map map);
  2. 编写对应的mapper配置文件

    <update id="updateBlog" parameterType="map">
    update blog
    <set>
    <if test="title != null">
    title = #{title},
    </if>
    <if test="author != null">
    author = #{author}
    </if>
    </set>
    where id = #{id}
    </update>

4. CHOOSE语句

  • 有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
  1. 编写接口方法

    List<Blog> queryBlogChoose(Map map);
  2. 编写对应的mapper配置文件

    <select id="selectBlogChoose" 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>
    adn views = #{views}
    </otherwise>
    </choose>
    </where>
    </select>

5. SQL片段

  • 有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用

  • 提取SQL片段:

    <sql id="if-title-author">
    <if test="title != null">
    title = #{title}
    </if>
    <if test="author != null">
    and author = #{author}
    </if>
    </sql>
  • 引用SQL片段:

    <select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
    <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
    <include refid="if-title-author"></include>
    <!-- 在这里还可以引用其他的 sql 片段 -->
    </where>
    </select>
  • 最好基于 单表来定义 sql 片段,提高片段的可重用性

  • 在 sql 片段中不要包括 where

6. ForEach

需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

  1. 编写接口

    List<Blog> queryBlogForeach(Map map);
  2. 编写对应的mapper配置文件

    <select id="queryBlogForeach" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <!--
    collection:指定输入对象中的集合属性
    item:每次遍历生成的对象
    open:开始遍历时的拼接字符串
    close:结束时拼接的字符串
    separator:遍历对象之间需要拼接的字符串
    select * from blog where 1=1 and (id=1 or id=2 or id=3)
         -->
           <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
              id = #{id}
           </foreach>
       </where>
    </select>
  3. 总结:其实动态sql语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的sql语句出来,然后在通过mybatis动态sql对照着改,防止出错

MyBatis笔记(六)的更多相关文章

  1. Mybatis笔记六:Mybatis中SqlSessionFactoryBuilder/SqlSessionFactory/SqlSession/映射器实例的作用域(Scope)和生命周期

    SqlSessionFactoryBuilder 这个类可以被实例化.使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了.因此 SqlSessionFactoryBuilder ...

  2. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  3. 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...

  4. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  5. Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  6. Python学习笔记六

    Python课堂笔记六 常用模块已经可以在单位实际项目中使用,可以实现运维自动化.无需手工备份文件,数据库,拷贝,压缩. 常用模块 time模块 time.time time.localtime ti ...

  7. Mybatis笔记二:接口式编程

    目录 旧方法的弊端 接口式编程 接口式编程的好处 接口式编程的增删改查 旧方法的弊端 在Mybatis笔记一中,我们使用命名空间+id的方式实现了Mybatis的执行,不过这里的命名空间是我们随便写的 ...

  8. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  9. Django开发笔记六

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...

  10. python3.4学习笔记(六) 常用快捷键使用技巧,持续更新

    python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...

随机推荐

  1. yarn create & npx & npm init

    yarn create & npx & npm init https://www.npmtrends.com/npm-vs-npx-vs-yarn demo https://www.n ...

  2. Nestjs 设置https

    文档 只是用https import * as fs from 'fs'; import { NestFactory } from '@nestjs/core'; import { AppModule ...

  3. css icons fontawesome-free

    官网 examples v4.7.0 cdnjs icons basic-use 安装 λ npm install --save @fortawesome/fontawesome-free fa前缀在 ...

  4. WPF 如何修改button圆角(经典)

    本人想设置Button为圆角,奈何搜索百度,找到的全是坑爹答案,现总结如下: 1. 需要添加button 的template. 2. 设置border的时候,必须要设置background, 否则会提 ...

  5. Vue(1)

    一:概述 Vue是一套用于构建用户界面的渐进式JavaScript框架,与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用.Vue的核心库只关心视图层,不仅易于上手,还便于与第三方库或既有项目 ...

  6. 【重磅】iNeuOS工业互联平台,系统集成业务模型和WEB组态视图建模集成3D模型

    目       录 1.      概述... 1 2.      平台演示... 2 3.      系统集成业务模型... 2 4.      WEB组态视图建模集成3D模型... 3 5.    ...

  7. new String("abc"),到底在不在常量池中存储"abc"?

    String str = new String("Hello World"); 问之:这行代码到底有没有在字符串常量池中创建"Hello World"字符串呢? ...

  8. ReactElement源码笔记

    ReactElement 源码笔记 ReactElement通过 createElement创建,调用该方法需要 传入三个参数: type config children type指代这个ReactE ...

  9. POJ-3281(最大流+EK算法)

    Dining POJ-3281 这道题目其实也是网络流中求解最大流的一道模板题. 只要建模出来以后直接套用模板就行了.这里的建模还需要考虑题目的要求:一种食物只能给一只牛. 所以这里可以将牛拆成两个点 ...

  10. CVE-2019-2618 任意文件上传

    漏洞描述:CVE-2019-2618漏洞主要是利用了WebLogic组件中的DeploymentService接口,该接口支持向服务器上传任意文件.攻击者突破了OAM(Oracle Access Ma ...