07 动态 SQL 语句

简介

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

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

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

1. if

if判断使用

<select id="selectOne" resultType="int">
    select * from product where 1 = 1
    <if test="money != null">
        and money > #{money}
    </if>
</select>

注意:第一个money代表实体类的属性名称,第二个money代表表字段名称,第三个是参数

2. choose, when, otherwise 多个条件判断

<choose>
    <when test="userName != null">
        and userName like ${userName}
    </when>
    <when test="id != null">
        and id = #{id}
    </when>
    <otherwise>
        and password is not null
    </otherwise>
</choose>

3. where、set

where会只能添加或者消减逻辑运算符

select * from product
<where>
    <if test = "userName != null">
        and userName link ${userName}
    </if>
    <if test="id != null">
        and id = #{id}
    </if>
</where>

set标记用于update操作,能够智能赋值

update product
<set>
    <if test="productName != null">
        productName = #{productName},
    </if>
    <if test="id != null">
        id = #{id},
    </if>
</set>

4. trim 标记=格式化标记,是一个更加智能化的标记。可以与其他标记组合完成where与set标记的功能

属性属性说明
prefix增加前缀
suffix增加后缀
prefixOverrides自动判断前置
suffixOverrides自动判断后置

用trim替换set

<trim prefix="set" suffixOverrides=",">
    <if test="userName != null and userName != '' ">
        userName = #{userName}
    </if>
</trim>

用trim代替where

select * from product
<trim prefix="where" prefixOverrides="and|or">
    <if  test="userName != null">
        and userName like ${userName}
    </if>
    <if test="id != null">
        and id = #{id}
    </if>
</trim>

5. foreach 标记

foreach 标记 表示循环

属性说明
item每一次迭代结果
collection循环集合或指定类型
separator元素之间的分割符号,可选
open开始符号,可选
close关闭符号,可选
indexlist和数组的序号,可选
<insert id="addUserInfoAll" parameterType="java.util.List">
    INSERT into userinfo(userName,PASSWORD,email) values
    <foreach collection="list" item="lt" separator=",">
        (#{lt.userName},#{lt.password},#{lt.email})
    </foreach>
</insert>

6. bind

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

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

7. 多数据库支持

一个配置了“_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>

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

MyBatis 从 3.2 开始支持可插拔脚本语言,这允许你插入一种脚本语言驱动,并基于这种语言来编写动态 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 项目。

你前面看到的所有 xml 标签都是由默认 MyBatis 语言提供的,而它由别名为 xml 的语言驱动器 org.apache.ibatis.scripting.xmltags.XmlLanguageDriver 所提供。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值