MyBatis动态SQL标签的用法详解

作者:--清风徐来-- 时间:2021-07-24 10:38:56 

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=#{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 #{title}
   </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 项目。

来源:https://www.cnblogs.com/zjl6/p/6965361.html

标签:MyBatis,动态,SQL,标签
0
投稿

猜你喜欢

  • 下载软件后使用c#获取文件的md5码示例

    2022-02-08 21:39:58
  • Java处理InterruptedException异常的理论与实践

    2023-07-25 03:22:33
  • 分布式系统下调用链追踪技术面试题

    2023-11-25 05:55:00
  • 解决Springboot启动报错:类文件具有错误的版本61.0,应为 52.0

    2023-03-13 02:16:11
  • C#通用邮件发送类分享

    2022-05-03 01:35:36
  • Java读取TXT文件内容的方法

    2023-11-23 22:33:41
  • 超详细的Java 问题排查工具单

    2023-02-10 06:02:17
  • IDEA基于支付宝小程序搭建springboot项目的详细步骤

    2021-10-30 22:44:46
  • SpringBoot文件上传功能的实现方法

    2021-11-23 11:24:27
  • JAVA文件扫描(递归)的实例代码

    2022-04-08 08:37:20
  • C#日期控件datetimepicker保存空值的三种方法

    2021-11-14 19:22:38
  • 基于spring中的aop简单实例讲解

    2023-10-16 21:01:10
  • Springboot mybatis plus druid多数据源解决方案 dynamic-datasource的使用详解

    2021-08-01 19:27:32
  • spring boot学习笔记之操作ActiveMQ指南

    2023-09-12 20:11:52
  • Java 实战范例之员工管理系统的实现

    2023-03-31 08:09:33
  • Java面向对象基础知识之封装,继承,多态和抽象

    2022-11-18 07:35:59
  • java实现简单斗地主(看牌排序)

    2023-09-12 14:42:40
  • SpringBoot中配置Web静态资源路径的方法

    2023-10-26 03:49:21
  • 深入探究如何使用Java编写MapReduce程序

    2022-10-17 18:40:04
  • Java实现简单的酒店管理系统

    2022-05-10 01:32:12
  • asp之家 软件编程 m.aspxhome.com