1.MyBatis动态SQL

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

通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。

动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

2.动态SQL标签:if,choose (when, otherwise),trim (where, set),foreach

2.1 if标签:直接上代码

<select id="queryByIdAndTitle"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 1=1 
  <if test="id!= null and title!=null">
    AND id=#{id} and title=#
  </if>
</select>

注:if标签一般用于非空验证,如上例,若id为空,if标签里的代码,将不会执行,反之,则会执行。

2.2 choose(when,otherwise)标签:直接上代码

<select id="queryBy"
     resultType="Blog">
  SELECT * FROM BLOG WHERE 1=1
  <choose>
    <when test="title != null">
      AND title like #
    </when>
    <otherwise>
      AND id= 1
    </otherwise>
  </choose>
</select>

注:choose(when,otherwise)标签相当于switch(case,default) ,如上例,若title 为空,when标签里的代码,将不会执行,默认执行otherwise标签里面的代码。

2.3 trim(where,set)标签:直接上代码

<select id="queryBy" resultType="com.scme.pojo.User" parameterType="com.scme.pojo.User">
                 select * from user 
                 <where>
                         <if test="username!=null and password!=null">
                             and username=#{username} and password=#{password}
                         </if>
                 </where>
</select>

注:假设上例传入的username,password不为空,代码就可以运行成功!但朋友们可能有疑问了,实际上执行的sql语句是什么呢?其实,sql为:select * from user

 where username=? and password=?  朋友们是否发现,where标签代替了sql中where关键字,但if中的and不见了。其实where标签可以自动去除是“AND”或“OR”开头的sql中的“AND”或“OR”关键字。

如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制sql,实现where标签的效果。代码如下:

<select id="queryBy" resultType="com.scme.pojo.User" parameterType="com.scme.pojo.User">
                 select * from user 
                 <trim prefix="WHERE" prefixOverrides="AND |OR ">
                          <if test="username!=null and password!=null">
                             and username=#{username} and password=#{password}
                         </if>
                </trim>
                 <!-- 效果同上
          <where>
                         <if test="username!=null and password!=null">
                             and username=#{username} and password=#{password}
                         </if>
                 </where> -->
         </select>

set标签,代码如下:

<update id="updateUser" parameterType="com.scme.pojo.User">
                 update user 
                 <set>
                     <if test="username!=null">
                             username=#{username}
                     </if>
                 </set>
                 <where> 
                     <if test="id!=null">
                             id=#{id}
                     </if>
                 </where>
         </update>

注:set标签功能和where标签差不多,set标签代替了sql中set关键字,set标签可以自动去除sql中的多余的“,”

同理,trim标签也可以实现set标签的功能

<update id="updateUser" parameterType="com.scme.pojo.User">
                 update user 
         <trim prefix="set" prefixOverrides=",">
              <if test="username!=null"> username=#{username} </if> 
        </trim>
  
         <where> 
    
            <if test="id!=null"> id=#{id} </if> 
          
        </where>
 </update>

2.4 foreach标签:foreach标签实现批量删除,直接上代码

<delete id="batchDelete" parameterType="java.lang.String">
  delete from user
  where id in
  <foreach item="id" index="index" collection="list"
      open="(" separator="," close=")">
        #{id}
  </foreach>
</delete >

注:foreach标签可迭代任何对象(如列表、集合等)和任何的字典或者数组对象传递给foreach作为集合参数,当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。collection标签可以填('list','array','map')。

foreach元素的属性主要有 item,index,collection,open,separator,close。

item表示集合中每一个元素进行迭代时的别名;

index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置;

open表示该语句以什么开始,

separator表示在每次进行迭代之间以什么符号作为分隔符;

close表示以什么结束。

3.bind

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

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

4.Multi-db vendor support

一个配置了“_databaseId”变量的 databaseIdProvider 对于动态代码来说是可用的,这样就可以根据不同的数据库厂商构建特定的语句。比如下面的例子:

<insert id="insert">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    <if test="_databaseId == 'oracle'">
      select seq_users.nextval from dual
    </if>
    <if test="_databaseId == 'db2'">
      select nextval for seq_users from sysibm.sysdummy1"
    </if>
  </selectKey>
  insert into users values (#{id}, #{name})
</insert>

动态 SQL 中可插拔的脚本语言

MyBatis 从 3.2 开始支持可插拔的脚本语言,因此你可以在插入一种语言的驱动(language driver)之后来写基于这种语言的动态 SQL 查询。

可以通过实现下面接口的方式来插入一种语言:

public interface LanguageDriver {
  ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
  SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
  SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
}

一旦有了自定义的语言驱动,你就可以在 mybatis-config.xml 文件中将它设置为默认语言:

<typeAliases>
  <typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/>
</typeAliases>
<settings>
  <setting name="defaultScriptingLanguage" value="myLanguage"/>
</settings>

除了设置默认语言,你也可以针对特殊的语句指定特定语言,这可以通过如下的 lang 属性来完成:

<select id="selectBlog" lang="myLanguage">
  SELECT * FROM BLOG
</select>

或者在你正在使用的映射中加上注解 @Lang 来完成:

public interface Mapper {
  @Lang(MyLanguageDriver.class)
  @Select("SELECT * FROM BLOG")
  List<Blog> selectBlog();

注意 可以将 Apache Velocity 作为动态语言来使用,更多细节请参考 MyBatis-Velocity 项目。

到此这篇关于MyBatis动态SQL标签的用法详解的文章就介绍到这了,更多相关MyBatis动态SQL标签内容请搜索程序员的世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员的世界!

java MyBatis动态SQL标签的用法详解的更多相关文章

  1. 使用JavaSE来模拟斗地主

    通过模拟斗地主案例来练习集合的使用结果预览:每次发牌后,三位玩家的手牌是随机的并且已经按照手牌大小排完序,运行两次验证手牌的随机性。马老师的牌还不错,芜湖~起飞思路:1.创建HashMap,键是编号,值是牌。2.创建ArrayList,存储编号。3.创建花色数组和点数数组。4.从0开始往HashMa......

  2. Java 生成随机字符的示例代码

    示例代码:import java.util.Random;import java.util.UUID;public class Dept {/*** 生成随机字符串 uuid*/public static String getUUID() {return UUID.randomUUID().toSt......

  3. spring使用RedisTemplate操作Redis数据库

    一.什么是RedisRedis是一个非关系型数据库,具有很高的存取性能,一般用作缓存数据库,减少正常存储数据库的压力。Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。下面......

  4. Java-web易混淆知识点整理

    Java-web易混淆知识点:post和get区别,相对路径和绝对路径,重定向和请求转发区别,Cookie和session的区别,jsp内置对象和EL内置对象的区别与联系,四大域对象的区别,活化与钝化,jsp九大内置对象,EL内置对象Java-web易混淆知识点 post和get区别post:数据不......

  5. Java 反射修改类的常量值、静态变量值、属性值

    前言有的时候,我们需要修改一个变量的值,但变量也许存在于 Jar 包中或其他位置,导致我们不能从代码层面进行修改,于是我们就用到了下面的场景,通过反射来进行修改变量的值。定义一个实体类class Bean{ private static final Integer INT_VALUE = 100;......

  6. java中Map、Set、List的简单使用教程(快速入门)

    Map、Set、ListList的常用方法1、创建List list = new ArrayList<>(); List list = new LinkedList<>(); //同时可以作为链表用List> list = new ArrayList<>()......

  7. java ArrayBlockingQueue的方法及缺点分析

    提到ArrayBlockingQueue的方法,想必大家都不陌生,我们在入队和出队的时候,接触了不少这方面的函数。当然ArrayBlockingQueue中的方法也不止于此,今天我们就全部为大家罗列出来,也算是做一个学习方向上的指引。然后就其中的peek方法带来实例介绍,并说明ArrayBlocki......

  8. 这么优雅的Java ORM没见过吧

    Java的ORM框架有很多,但由于Java语言的限制大部分都不够优雅也不够简单,所以作者只能另辟蹊径造轮子了。照旧先看示例代码了解个大概,然后再解释实现原理。一、ORM示例1. Insertpublic CompletableFuture insert() {var obj = new sys.en......

  9. Java 找不到或无法加载主类的修复方法

    有时,当我们运行Java程序时,我们可能会看到“找不到或无法加载主类”。原因很容易猜测:JVM找不到主类并给出了这个错误。但是为什么不能呢?在本文中,我们将讨论找不到主类的可能原因。另外,我们将看看如何修复它们。示例程序我们将从HelloWorld程序开始:public class HelloWor......

  10. java中DelayQueue实例用法详解

    在阻塞队里中,除了对元素进行增加和删除外,我们可以把元素的删除做一个延迟的处理,即使用DelayQueue的方法。这里的删除需要一定的时间才能生效,有点类似于过期处理的理念。下面我们就DelayQueue的概念、特点进行讲解,然后在代码示例中体会DelayQueue的使用。1.概念是一个带有延迟时间......

随机推荐

  1. R语言之xlsx包读写Excel数据的操作

    感谢Adrian A. Drǎgulescu发布的xlsx包xlsx包提供了必要的工具来与Excel 2007进行交互。用户可以阅读和编写xlsx,并可以通过设置数据格式、字体、颜色和边框来控制电子表格的外观。设置打印区域,缩放控制,创建分割和冻结面板,添加页眉和页脚。包使用Apache POI项目......

  2. python中openpyxl和xlsxwriter对Excel的操作方法

    前几天,项目中有个小需求:提供Excel的上传下载功能,使用模块:openpyxl 和 xlsxwriter,这里简单记录一下。1.简介Python中操作Excel的库非常多,为开发者提供了多种选择,如:xlrd、 xlwt、xlutils、xlwings、pandas、 win32com、open......

  3. Android在fragment中编写toobar的步骤详解

    第一步的话就是首先导入我们的依赖的包:compile 'com.android.support:appcompat-v7:23.3.0'第二步的话就是准备我们的布局文件和我们的item在这的话我是将我们的toobar单独的放在一个布局文件中的方便以后的调用以及将我们的主题改为我们noactionba......

  4. 如何用CocosCreator实现射击小游戏

    分析下制作步骤:1. 准备好资源,搭建场景资源的话可以自己到网上找,也可以直接用我的也行;创建好相应文件夹,把资源放到res文件夹下;搭建场景:第一步:创建一个单色精灵(Script) bg 背景, 设置好颜色,加一个Widget组件,使其充满屏幕;第二步: 在bg节点下创建top和button空节......

  5. nodejs的错误处理过程记录

    本文以连接错误ECONNREFUSED为例,看看nodejs对错误处理的过程。 假设我们有以下代码1. const net = require('net'); 2. net.connect({port: 9999})如果本机上没有监听9999端口,那么我们会得到以下输出。1. events.......

  6. Python基础(中篇)

    数据类型的常用方法,条件语句,循环语句。本篇文章主要内容:数据类型的常用方法,条件语句,循环语句。在开始正篇之前我们先来看看上一篇留下的题目。题目:定义一个字典a,有两个键值对:一个键值对key是可乐,value是18;另一个键值对key是python,value是列表形式的1,2,3,4,5。答案......

  7. Python优化机制:常量折叠

    英文:https://arpitbhayani.me/blogs/constant-folding-python作者:arprit译者:豌豆花下猫(“Python猫”公众号作者)声明:本翻译是出于交流学习的目的,基于 CC BY-NC-SA 4.0 授权协议。为便于阅读,内容略有改动。每种编程语言为......

  8. 如何在Vue中实现Svelte的Defer Transition

    最近观看了Rich Harris的<Rethinking Reactivity>视频,惊叹于Svelte框架的高效同时,还发现了Vue所不具备的一些关于动画的原生支持—defer transitions.先看看Svelte所谓的defer transition的效果吧。这是使用Svelt......

  9. 详解Python小数据池和代码块缓存机制

    前言本文除"总结"外,其余均为认识过程;3.7.5;这部分官方文档不知道在哪里找,目前没有找到,有谁知道的可以麻烦留言吗? 谢谢了!总结:如果在同一代码块下,则采用同一代码块下的缓存机制;如果是不同代码块,则采用小数据池的驻留机制;需要注意的是,交互式输入时,每个命令都是一个代码......

  10. 用Python制作灯光秀短视频的思路详解

    一、引言2021年4月8日武汉重启一周年,这是个值得庆祝的日子,作为一个武汉人和一个死宅程序员,老猿也想在这个日子留下点什么。想起武汉长江两岸的灯光秀,顿时有了主意,那就用程序实现一个武汉重启庆祝的灯光秀短视频吧,于是在4月7日晚开始构思和着手开发,4月8日晚终于顺利完成,并且通过使用OpenCV、......