java--MyBatis 动态SQL

40 篇文章 0 订阅
32 篇文章 0 订阅

MyBatis 动态SQL

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。


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


if

动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。

<select id="findStudentNameById" parameterType="int" resultType="StudentInfo">
        select * from student
        <where>
            <trim suffix="" suffixOverrides="and">
                <if test="classId!=null">
                    classId=#{classId}
                </if>
                <if test="studentName!=null and studentName!=''">
                   and studentName like concat(concat('%',#{studentName}),'%')
                </if>
            </trim>
        </where>
    </select>
  • suffix:在trim标签内sql语句加上后缀
  • prefix:在trim标签内sql语句加上前缀
  • suffixOverrides:指定去除多余的后缀内容
  • prefixOverrides:指定去除多余的前缀内容

比如:suffixOverrides=”and”,去除trim标签内sql语句多余的后缀”and”



choose, when, otherwise

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


    <select id="findStudentByChoose" resultType="studentInfo">
        select * from student where 1=1
        <choose>
            <when test="studentName!=null and studentName!=''">
                and studentName like concat(concat('%',#{studentName}),'%')
            </when>
            <when test="studentAge!=0">
                and studentAge>#{studentName}
            </when>
            <otherwise>
                and classId=#{classId}
            </otherwise>
        </choose>
    </select>
  • choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。


trim, where, set

where 元素知道只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。
类似的用于动态更新语句的解决方案叫做 set。set 元素可以被用于动态包含需要更新的列,而舍去其他的。


    <update id="update" parameterType="StudentInfo">
        update student
        <trim suffix="where studentId=#{studentId}" suffixOverrides=",">
            <set>
                <if test="studentName!=null">studentName=#{studentName},</if>
                <if test="studentSex!=null">studentSex=#{studentSex},</if>
                <if test="studentAddress!=null">studentAddress=#{studentAddress},</if>
                <if test="studentAge!=null">studentAge=#{studentAge},</if>
                <if test="classId!=null">classId=#{classId},</if>
            </set>
        </trim>
    </update>
  • trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。


foreach

动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

    <select id="findStudentByMap" resultType="StudentInfo">
        select * from student where studentName like concat(concat('%',#{studentName}),'%') and classId in
        <foreach collection="list" item="map" open="(" separator="," close=")">
            #{map}
        </foreach>
    </select>

在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:

  • 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list 。
  • 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array 。
  • 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key。


举个例子:

mapper 方法:

public List<StudentInfo> findStudentByMap(Map<String,Object> map);

xml 映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.zbw.mapper.StudentInfoMapper">
    <select id="findStudentByMap" resultType="StudentInfo">
        select * from student where studentName like concat(concat('%',#{studentName}),'%') and classId in
        <foreach collection="list" item="map" open="(" separator="," close=")">
            #{map}
        </foreach>
    </select>

test 类:

package cn.zbw.test;

import cn.zbw.entity.StudentInfo;
import cn.zbw.mapper.StudentInfoMapper;
import cn.zbw.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Test07 {
    public static void main(String[] args) {
        test07();
    }

    private static void test07() {
        SqlSession session = MybatisUtils.getSession();
        HashMap<String, Object> map = new HashMap<>();
        List list = new ArrayList();
        list.add(2);
        map.put("studentName","冰");
        map.put("list",list);
        List<StudentInfo> stuList = session.getMapper(StudentInfoMapper.class).findStudentByMap(map);
        for (StudentInfo stu : stuList) {
            System.out.println(stu.getStudentName()+"\t"+stu.getStudentAddress());

        }
    }
}

查询结果:
在这里插入图片描述

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值