文档章节

【MyBatis】学习纪要六:动态SQL

冯文议
 冯文议
发布于 2018/04/27 00:34
字数 914
阅读 102
收藏 0

引言

动态SQL:Dynamic SQL。

本节我们来通过 MyBatis 的官方文档进行学习。

Description(描述)

官方描述如下:

One of the most powerful features of MyBatis has always been its Dynamic SQL capabilities. If you have any experience with JDBC or any similar framework, you understand how painful it is to conditionally concatenate strings of SQL together, making sure not to forget spaces or to omit a comma at the end of a list of columns. Dynamic SQL can be downright painful to deal with.

While working with Dynamic SQL will never be a party, MyBatis certainly improves the situation with a powerful Dynamic SQL language that can be used within any mapped SQL statement.

The Dynamic SQL elements should be familiar to anyone who has used JSTL or any similar XML based text processors. In previous versions of MyBatis, there were a lot of elements to know and understand. MyBatis 3 greatly improves upon this, and now there are less than half of those elements to work with. MyBatis employs powerful OGNL based expressions to eliminate most of the other elements:

● if ● choose (when, otherwise) ● trim (where, set) ● foreach

My View

上面这段话,总结起来就三点:

  • MyBatis 在动态SQL这块很强大。

  • 你需要会 OGNL 表达式

  • if/choose/trim/foreach

OGNL

用法看这里:OGNL指南

另外,支持转义符,所以,看一下转义:

html转义符.png

if/where/trim/choose/foreach

  • if 表示 判断
  <if test="title != null">
    AND title like #{title}
  </if>
  • where

我们总会在if标签里写AND,那么当第一个不存在时就会出问题: sql: ...WHERE AND ...

因此 where 是解决这个问题的

  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
  • trim

有人会说了,既然写在前面有问题,那可不可以写在后面呢?当然可以。

来看些 trim 的用法:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

-----

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

总结一下: prefix:前面加什么 prefixOverrides:前面忽略掉什么 suffix:后缀 suffixOverrides:后面忽略掉什么

  • choose
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
  • foreach

遍历一个集合。

collection:指定要遍历的集合: list类型的参数会特殊处理封装在map中,map的key就叫list item:将当前遍历出的元素赋值给指定的变量 separator:每个元素之间的分隔符 open:遍历出所有结果拼接一个开始的字符 close:遍历出所有结果拼接一个结束的字符 index:索引。遍历list的时候是index就是索引,item就是当前值

  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>

set

    <update id="testUpdate">
        UPDATE
          user
        <set>
            <if test="user.name != null">name = #{user.name},</if>
            <if test="user.age != null and user.age >= 0">age = #{user.age}</if>
        </set>
        <where>
            <if test="user.id != null and user.id > 0">id = #{user.id}</if>
        </where>
    </update>

批量插入

  • 方法一:
    <insert id="testBatchInsert1">
        INSERT INTO
          user(name, age)
        VALUES
        <foreach collection="users" index="i" item="k" separator=",">
            (
            <if test="k.name != null">#{k.name}</if>
            ,
            <if test="k.age != null and k.age >= 0">#{k.age}</if>
            )
        </foreach>
    </insert>
  • 方法二:
    <insert id="testBatchInsert2">

        <foreach collection="users" index="i" item="k" separator=";">
            INSERT INTO
              user(name, age)
            VALUES(
            <if test="k.name != null">#{k.name}</if>
            ,
            <if test="k.age != null and k.age >= 0">#{k.age}</if>
            )
        </foreach>
    </insert>

注意

1、数据库的url应该如下配置:

spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_demo?allowMultiQueries=true

2、此方法返回的影响行数不正确。

==> Preparing: INSERT INTO user(name, age) VALUES( ? , ? ) ; INSERT INTO user(name, age) VALUES( ? , ? ) ==> Parameters: n3(String), 11(Integer), n4(String), 12(Integer) <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@64fc097e] rs num : 1

_parameter and _databaseId

_parameter,参数 _databaseId,当前数据库的Id

bind

关于数据绑定,MyBatis官网提供的例子如下:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

引用sql

有些重复的,可以抽取出来

后记

测试代码:DynamicSQL-Demo

需要说明的是:为了保持测试风格,有些返回值类型不正确,导致测试报错,但这并不影响着一节的学习,因为你能够看到sql和结果。

© 著作权归作者所有

冯文议
粉丝 11
博文 47
码字总数 47895
作品 0
成都
高级程序员
私信 提问
【MyBatis】学习纪要十一:逆向工程

写在前面的话 前面学习MyBatis的运行原理,刚学完,回头想想还是非常复杂的,也因为之前没有这样去分析过源码,所以这一节算是卡住了,可能会花一定的时间,为了不卡住学习进度,所以我们继续...

Wenyi_Feng
2018/05/10
51
0
Spring-MyBatis-SQL拦截

一、应用场景 在项目中, 针对敏感数据等重要数据的列表查询,为避免数据泄露等, 需要针对数据添加权限。 场景:有三个账号:员工A、员工B、经理A;专员A、B 属于经理A的下级,且他们属于同...

ge洋
07/16
124
0
深入浅出MyBatis_Index

深入浅出MyBatis系列 【深入浅出MyBatis系列一】MyBatis入门 【深入浅出MyBatis系列二】配置简介(MyBatis源码篇) 【深入浅出MyBatis系列三】Mapper映射文件配置 【深入浅出MyBatis系列四】...

陶邦仁
2015/12/22
1K
0
【MyBatis】学习纪要七:缓存(一)

写在前面的话 缓存对数据库来说,不是必须,但对于系统来说,缓存是少不了的。我在之前的开发中没有学缓存,也没用到,所以这一次学MyBatis,就来认真学一下,如果你跟我一样,那就来跟我一起...

Wenyi_Feng
2018/05/02
28
0
MyBatis体系大纲

1.MyBatis优势 2.MyBatis总体流程 3.MyBatis功能架构 4.MyBatis框架架构 5.MyBatis动态SQL语句 5.1.MyBatis动态传入表名,字段名参数 要实现动态传入表名、列名,需要做如下修改 添加属性sta...

微尘鉴
2015/09/17
92
0

没有更多内容

加载失败,请刷新页面

加载更多

面向海量数据的极致成本优化-云HBase的一体化冷热分离

前言 随着业务的持续发展,业务数据库存储量会持续增长。通常数据量过亿时,就需要考虑做分库分表,或者选择扩展能力更好的NOSQL/NewSQL数据库,如HBase就可以单表支持PB级数据,足够满足大多...

阿里云官方博客
28分钟前
3
0
最新最全国内外架构开源技术干货资料

大家好,废话不多说,整理了精心收集了各类资源。 声明,如侵犯个人利益,请联系小编,会立即删除相关资料。 领取方式在文末 求转发列表 好了,由于资源太多啦,就不一一列举了。 大家按照下...

泥瓦匠BYSocket
30分钟前
6
0
springmvc jsp访问不了css

在jsp中引入css,一直报404错误,直接访问css,也无法访问 将css文件移出WEB-INF,因为处于安全性考虑,这个目录禁止外部访问。 当引用css时,可以直接用绝对路径${pageContext.request.conte...

沉迷于编程的小菜菜
32分钟前
4
0
android 系统版本 9.1网络请求遇到坑

网络请求异常: E/http: CLEARTEXT communication to plat.xunlinkeji.cn not permitted by network security policy 在res下新建一个xml目录 创建名为network_security_config.xml 文件 ,该......

MrLins
50分钟前
5
0
Istio 1.3 发布,HTTP 遥测不再需要 Mixer

> 原文链接:Istio 1.3 发布,HTTP 遥测不再需要 Mixer Istio 是 Google、IBM 和 Lyft 联合开源的服务网格(Service Mesh)框架,旨在解决大量微服务的发现、连接、管理、监控以及安全等问题...

米开朗基杨
今天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部