Mybatis 学习(三)——动态SQL


如果我们有复杂的业务,我们需要更复杂的SQL语句,往往需要拼接,而拼接SQL语句,稍微不注意,由于引号、空格等缺失都会导致错误,而Mybatis 提供的动态SQL 使得拼接SQL语句变得容易。

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

1、if 标签

if 标签和我们java 里面的if语句作用是一样的,下面代码里的test 是判断表达式,判断后面的条件时否成立

<select id="getStu" parameterType="com.tulun.bean.Student" resultType="com.tulun.bean.Student">
        select * from student
        where
        <if test="id != null">
            id = #{id}
        </if>
        <if test="name != null &amp;&amp; name != &quot;&quot;">
            and name = #{name}
        </if>
    </select>
@Test
    public void test(){
        StudentDynamicSql mapper = session.getMapper(StudentDynamicSql.class);
        Student stu = mapper.getStu(new Student(1, "", "123456"));
        System.out.println(stu);
    }

在这里插入图片描述
从结果来看,第二个if 标签里的语句是不成立的,最后我们生成的SQL语句也没有第二个条件。

2、where 标签

还是上面的例子,我们这次设置id 为null 来看看会发生什么?

@Test
    public void test(){
        StudentDynamicSql mapper = session.getMapper(StudentDynamicSql.class);
        Student stu = mapper.getStu(new Student(null, "wjm", "123456"));
        System.out.println(stu);
    }

在这里插入图片描述
它抛出了一串异常并且打印出如下日志,当第一个条件不成立的时候,这个拼接而成的语句是由问题的。这里不得不说一下标签了。
标签就是我们SQL语句中的where,如果用sql语句的where,那么当第一个条件不满足时,那么后面的条件前都会加一个and,SQL语句就会出现错误,如果后面生成对的语句是以and 或or 开头的,那么标签会自动得到取掉开头的and,or。
我们修改一下映射文件,还是将id 设为null,我们看一下会发生什么?

<select id="getStu" parameterType="com.tulun.bean.Student" resultType="com.tulun.bean.Student">
        select * from student
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            <if test="name != null &amp;&amp; name != &quot;&quot;">
                and name = #{name}
            </if>
        </where>
    </select>

在这里插入图片描述
生成的 SQL 语句没问题了, 语句帮我们处理掉了前面的and

3、trim 标签

where 不能处理掉后面的and 或者其他的元素,在这里mybatis 还提供了另一个标签, 标签里面提供了这么几个元素

元素功能
prefix给拼接后的字符串增加一个前缀,可以添加where、set等任何值
suffix给拼接后的字符增加一个后缀
prefixOverrides前缀覆盖,标签体里的前面多余的字符去掉
suffixOverride后缀覆盖,标签体里的后面多余的字符去掉

通过 标签,原来的代码我们可以写成这个样子

 <select id="getStu" parameterType="com.tulun.bean.Student" resultType="com.tulun.bean.Student">
        select * from student
        <trim prefix="where" suffixOverrides="and">
            <if test="id != null">
                id = #{id} and
            </if>
            <if test="name != null &amp;&amp; name != &quot;&quot;">
                name = #{name}
            </if>
        </trim>
    </select>

在这里插入图片描述

4、choose 标签

choose:(when,otherwise)分支选择,相当于带了break的switch case
when:相当于case
otherwise:相当于default
只会进入一个,如果条件都不满足就进入otherwise,那么上面的例子我们可以再变一下。

    <select id="getStu" parameterType="com.tulun.bean.Student" resultType="com.tulun.bean.Student">
        select * from student
        <trim prefix="where" suffixOverrides="and">
            <choose>
              <when test="id != null">
                  id = #{id}
              </when>
              <when test="name != null &amp;&amp; name != &quot;&quot;">
                  name = #{name}
              </when>
              <otherwise>
                  pssward = #{passward}
              </otherwise>
            </choose>
        </trim>
    </select>
@Test
    public void test(){
        StudentDynamicSql mapper = session.getMapper(StudentDynamicSql.class);
        Student stu = mapper.getStu(new Student(null, "", "wjmpwd"));
        System.out.println(stu);
    }

看一看发生了什么。
在这里插入图片描述
在 的两个标签条件都不满足的情况下,进入了otherwise 标签。

5、foreach 标签

动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
foreach 标签里的几种参数

参数功能
collection指定要遍历的集合
ListList 类型的参数会特殊处理封装在map中,map的key就叫list
item将当前遍历出的元素赋给指定的变量
separator每个元素之间的分隔符
open遍历出所有结果拼接一个开始的字符
close遍历出所有结果拼接一个结束的字符

现在我们重新写一个接口,通过id 批量查找学生信息

    /**
     * 批量获取学生信息
     * @param list
     * @return
     */
    public List<Student> getStus(List<Integer> list);
<select id="getStus" parameterType="com.tulun.bean.Student" resultType="com.tulun.bean.Student">
        select * from student
        <trim prefix="where">
           id in
           <foreach collection="list" item="item" open="(" close=")" separator=",">
               #{item}
           </foreach>
        </trim>
    </select>

    @Test
    public void test(){
        StudentDynamicSql mapper = session.getMapper(StudentDynamicSql.class);
       /**
         * 批量获取学生信息
         */
        List<Student> stus = mapper.getStus(Arrays.asList(1, 2, 3, 4));
        for (Student stu:stus){
            System.out.println(stu);
        }
   }

在这里插入图片描述
最后生成的SQL语句是 select * from student where id in ( ? , ? , ? , ? )。
我们分析一下,

  • collection :就是我们方法参数的那个list
  • item:每次循环将取出的数据放入这个变量中
  • open:循环开开始拼接的字符串,在我们这个SQL语句中就是“(”
  • close:循环结束拼接的字符串,在我们这个SQL语句中就是“)”
  • separator:就是遍历过程中每个元素之间的分割符

你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。collection是传入的可迭代对象参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

6、两个内置参数

① _parameter: 代表整个参数

  • 单个参数:_parameter 就是这个参数
  • 多个参数:参数会被封装成map,_parameter就代表这个map。当多个参数时,可以通过_parameter.get(0)来获取参数
    获取单个学生那个例子,我们继续修改它
 <select id="getStu" parameterType="com.tulun.bean.Student" resultType="com.tulun.bean.Student">
        select * from student
          <if test="_parameter != null">
              <trim prefix="where">
                 <choose>
                     <when test="id != null">
                         id = #{_parameter.id}
                     </when>
                     <when test="name != null &amp;&amp; name !=  &quot;&quot;">
                         id = #{_parameter.name}
                     </when>
                     <otherwise >
                         pssward = #{_parameter.passward}
                     </otherwise>
                 </choose>
              </trim>
          </if>
    </select>

在这里插入图片描述
② _databaesId:如果配置了这个_databaesIdProvider标签,_databaesId 就是代表当前数据库的别名

7、bind

绑定一个表达式给一个变量,可以用这个变量来代替这个表达式
我们增加一个这样的接口

public Student getStu2();
<select id="getStu2" resultType="com.tulun.bean.Student">
        <bind name="n" value="'wjm'"></bind>
        select * from student where name = #{n}
    </select>

我们将"wjm" 这个表达式绑定给了n这个变量,表示在后面我们可以通过n这个变量来代替wjm,看看结果吧!
在这里插入图片描述

8、sql 标签和include标签

① sql标签:抽取可重用的sql片段,方便后面使用
② include:引用已经抽取的sql 查询,还可以定义一些property ,sql标签内部就能使用自定义的属性,使用${property}引用
我们来看一个小例子,修改一下我们刚刚写的那个方法。

 	<sql id="l">
        id,name,pssward
    </sql>
    
    <select id="getStu2" resultType="com.tulun.bean.Student">
        <bind name="n" value="'wjm'"></bind>
        select
        <include refid="l"/>
        from student where name = #{n}
    </select>

看看结果
在这里插入图片描述

总结
其实动态 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态sql 对照着改,防止出错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值