mybatis中动态sql的实现与使用

版权声明:原创文章,转载请说明出处 https://blog.csdn.net/Destiny_strive/article/details/82710835

首先引用一段mybatis文档中的话:

动态 SQL

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

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

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

一、if

二、where

三、set

四、trim

五、choose, when, otherwise

六、foreach

七、bind


下面记录各个元素的巧妙使用:

一、if

如果采用xml的方式配置mybatis,假设现在要做两个查询:

1.查询一个对象的所有记录。

2.查询一个对象所有记录中包含一个传过来的字符串的模糊查询。

那么不使用动态SQL应该这样写:(这样显得很麻烦)

<select id="productList" resultType="Product">
    select p.id,p.name,p.price from product p
</select>
<select id="getProductsLikeName" parameterType="String" resultType="Product">
    select p.id,p.name,p.price from product p where name like concat('%',#{nameaa},'%')
</select>

对应接口:

List<Product> productList();
List<Product> getProductsLikeName(String name);

采用if:如果没有传入Product对象就查询所有,传入了对象就根据product.name的值进行模糊查询,方便太多了。

<select id="list" resultType="Product" parameterType="Product">
    select p.id,p.name,p.price from product p
    <if test="name!=null">
        where name like concat('%',#{name},'%')
    </if>
</select>

对应接口:

List<Product> list();
List<Product> list(Product product);

二、where

如果有多个if来判断,前一个if不成立,可能就会出现多出一个and的错误情况。

where>标签会进行自动判断

如果任何条件都不成立,那么就在sql语句里就不会出现where关键字

如果有任何条件成立,会自动去掉多出来的 and 或者 or。

例如:除了根据name模糊查询,再加一个价格的筛选。

(如果不用where只用两个if,

    假设name没有传值,那么sql语句就会变成  select p.id,p.name,p.price from product p and price>#{price}

    这显然会报错。

 )

<select id="list" resultType="Product" parameterType="Product">
    select p.id,p.name,p.price from product p
   <where>
       <if test="name!=null">
           and name like concat('%',#{name},'%')
       </if>
       <if test="price!=null">
           and price>#{price}
       </if>
   </where>
</select>

三、set

在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:

name或者price有值的时候才进行sql拼接。

<update id="updateProduct" parameterType="Product" >
    update product
    <set>
        <if test="name!=null">name=#{name},</if>
        <if test="price!=null">price=#{price}</if>
    </set>
    where id=#{id}
</update>

四、trim

如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

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

例子:这里把<where>改为了<trim prefix="WHERE" prefixOverrides="AND |OR ">。

<select id="list" resultType="Product" parameterType="Product">
    select p.id,p.name,p.price from product p
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
       <if test="name!=null">
           and name like concat('%',#{name},'%')
       </if>
       <if test="price!=null">
           and price>#{price}
       </if>
    </trim>
</select>

例子:<set>改为了<trim prefix="SET" suffixOverrides=",">。

特别注意:我看的文档中提示出如果最后一个if不成立,删去的是后缀值,同时添加了前缀值。那么sql语句的结尾就会多出一个逗号。

<update id="updateProduct" parameterType="Product" >
    update product
    <trim prefix="SET" suffixOverrides=",">
        <if test="name!=null">name=#{name},</if>
        <if test="price!=null">price=#{price}</if>
    </trim>
    where id=#{id}
</update>

五、choose, when, otherwise

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

例子:如果传入的Product对象没有设置name和price的值,那么就执行查询id大于1的记录,如果name或price有值,那么就查询对应的,并且不执行<otherwise>中的语句。 非常的像switch语句。

<select id="list1" resultType="Product">
    SELECT p.id,p.name,p.price FROM product p
    <where>
        <choose>
            <when test="name != null">
                and name like concat('%',#{name},'%')
            </when>
            <when test="price !=null and price != 0">
                and price > #{price}
            </when>
            <otherwise>
                and id >1
            </otherwise>
        </choose>
    </where>
</select>

六、foreach

foreach标签通常用于in 这样的语法里。

例子:查询id为1和4的记录。

<select id="list3" resultType="Product">
    SELECT p.id,p.name,p.price FROM product p
    WHERE ID in
    <foreach item="item" index="index" collection="list"
             open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

七、bind

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

<!-- 本来的模糊查询方式 -->
<!--         <select id="list4" resultType="Product"> -->
<!--             select p.id,p.name,p.price from   product p  where name like concat('%',#{0},'%') -->
<!--         </select> -->

<select id="list4" resultType="Product">
    <bind name="likename" value="'%' + name + '%'" />
    select p.id,p.name,p.price from   product p  where name like #{likename}
</select>

引用书籍中的话:

bind取代模糊查询的好处是提高了代码的可移植性。

在进行模糊查询时,如果是MySQL数据库,常常用到的是一个concat,它用'%'和参数相连。然而在Oracle数据库则没有,Oracle数据库用连接符号”||“。 当我们有了bind元素,就不必使用数据库语言,而是使用MyBatis的动态SQL即可完成。

所以无论是MySQL还是Oracle都可以使用这样的语句,从而提高了代码的可移植性。

猜你喜欢

转载自blog.csdn.net/Destiny_strive/article/details/82710835