zoukankan      html  css  js  c++  java
  • 使用Mybatis实现动态SQL(一)

    使用Mybatis实现动态SQL

    作者 : Stanley 罗昊

    转载请注明出处和署名,谢谢!

    写在前面:

           *本章节适合有Mybatis基础者观看*

    前置说明

    我现在写一个查询全部的sql语句,这个对各位来说,想必应该是非常简单,我举个例子:

    select * from studnet //查询全部

    我现在需求又变了。我现在要根据年龄进行查询了,那是不是也依然很简单:

    select * from student where age = #{age} //根据年龄查询学生

    那么,我现在再来一个需求,根据年龄跟姓名来查:

    select * from student where age = #{age} and name=#{name};

    但是,我们仔细发现,我刚才在写sql语句,就需要复制粘贴,那也就意味着,在这以上的sql语句是重复的,也就是说三个语句里,查询的都是同一张表,只不过加了一些条件;

    因此,我没有必要写三次,其实我们写一次就够了

    如果使用动态sql来实现的话,就非常方便,比如:

                                    我第一次使用的时候,仅使用select * from student 仅仅的查询全部,用于初始化

                                    我第二次再去使用的时候 仅使用 where = age

                                    我第三次再去使用的时候 就成了 where = age and name =name

    可以灵活的控制sql语句,这就是动态sql;

    可以设想一下,如果没有动态sql,我们是不是一个功能模块,就要写三段sql语句,很显然让代码变的非常臃肿不整洁,效率还低,所以,在正常的企业开发当中,动态sql用点居多!

    动态SQL

    那么,到底怎么实现呢?这个,就用到了mybatis xml文件中的动态标签了;

    首先,我们需要看一下查询条件:本次业务涉及到查询所有、根据学生年龄查询、根据学生年龄并且根据学生姓名进行查询;

    查询所有,因为要在页面初始化中使用,所以页面加载之后需要展示出来,另外那些条件,就是几个筛选条件,可以利用他们满足自己的查询需要;

    现在,我们就根据以上业务来完成一个动态sql;

    在要进行查询的xml文件中编写:

    <select id = "selectAllorbynameAndage" resultType = "Student">
    
    select * from student where
    
    <if test = " name!= null and name!= ' ' ">//如果传过来的student对象有name属性,并且该属性不为空,便执行次条件
    
    student = #{name}
    
    </if>
    
    <if test = "age !=null and age != ' ' ">
    
    And student = #{age}
    
    </if>
    
    </select>

    讲解:

    1.if:什么叫if,就是如果有这么怎办,如果没怎么怎么办,在这里的意思就是,你现在查的时候,要是传入了一个名字,那么,我就根据你传过来的name进行查询。

    换句话说,如果你没传这个字段,那么是不是就不进入这个判断了,也就代表你没写这个where一样;

    用意:我现在传过来一个学生对象,如果这个学生对象包含了一个name属性,且name属性不为空,那么我就要把这个student = #{name}给加上

    if后面的test里面就写执行条件

    2.我们现在除了name之外,是不是还有可能有age;

    根据以上的业务,我们发现,也是有根据age进行查询的,那么,我们仅需在下面跟上一个if里面来写关于age的判决即可;

    但是值得注意的是,本次编写前面需要加上and;

    and:为什么在加and呢?

    我们可以设想一下,目前的sql语句是这样的:

    select * from student where name = #{name}

    如果不加and的话,是不是就变成了:

     select * from student where name = #{name}age = #{age}

    这样显然是不对的,sql语法都出错两,所以需要在前面加上and,加上and之后就是合法的sql语句了:

     select * from student where name = #{name}And age = #{age}

    解决sql语句解释失败

    那么,问题来了,以上写的那种方案是,name 跟 age 必须全部存在,才可以生效,一旦不存在,那么就会报错,我现在认定这个name时在时不在的情况;

    我举个例子,本次查询,仅仅按照age查询,这个时候,age传过来了,但是name没有传过来,因为我只查询age,肯定只用把age传过来,这个时候,name拿不到值,就导致了这样的sql语句:

    select * from student where And age = #{age}

    这就很明显,sql语句怎么可能写成这样,这个and就非常令人厌烦,为什么会导致成这样呢?

    还记得我们写的一个if标签吗?如果name = null and name = ‘ ’,我这条标签就不去执行一旦不去执行就变成以上那样了,原本有name是这样的:

     select * from student where name = #{name}And age = #{age}

    你现在name为空了,那就表明name  = #{name}就消失了

    这个and你也去不掉它,你一旦去掉了,又会造成另外一种sql语法非法,如何解决这个不协调的字段呢?

    两种解决方案

    第一种:

    <select id = "selectAllorbynameAndage" resultType = "Student">
    
    select * from student where 1 = 1
    
    <if test = " name!= null and name!= ' ' ">//如果传过来的student对象有name属性,并且该属性不为空,便执行次条件
    
    And student = #{name}
    
    </if>
    
    <if test = "age !=null and age != ' ' ">
    
    And student = #{age}
    
    </if>
    
    </select>

    我把studnt = name前面也加了一个and,但是这样做会导致本次sql语句不成立,没关系,我在where后面加了一个 1 = 1,就代表永远成立,也就是强制让数据库认下这个and;

    第二种【最佳/推荐】:

    <select id = "selectAllorbynameAndage" resultType = "Student">
    
    select * from student
    
    <where>
    
    <if test = " name!= null and name!= ' ' ">//如果传过来的student对象有name属性,并且该属性不为空,便执行次条件
    
    And student = #{name}
    
    </if>
    
    <if test = "age !=null and age != ' ' ">
    
    And student = #{age}
    
    </if>
    
    </where>
    
    </select>

    现在呢,我们直接用where标签把sql包裹,把主查询后面的where就删掉,因为已经不需要了,那么加上这个where标签后,sql变成什么样子了呢?

     select * from student <where> and  name = #{name}and age = #{age}

    这样的sql语句看似是不是像是那种有问题的sql语句,因为在where后面就有and,但是没关心,不用管,这个<where>标签是智能的,它会自动处理第一个and,不会处理第二个;

    什么意思呢?就是本次查询,如果你需要这个and,那么我就给你加上,如果你不需要这个and,我就不给你加,很显然,本次查询不需要这个and,所以就没给你加;

    这个时候,你把第一个and给删了,再去执行,你会发现跟没删一样,如果你加上这个and,你就会发现,跟没加一样,就是这么智能,非常便捷;

    但是,如果你把第二个或往后的and删了,就会出问题了,因为它只会帮你处理第第一个and;

    所以,原理是这样的:

    刚才我说了,如果没有name,那么第一个if就会消失,紧接着,age是不是就顶替name了,那么age就是第一个了

    <select id = "selectAllorbynameAndage" resultType = "Student">
    
    select * from student
    
    <where>
    
    <if test = "age !=null and age != ' ' ">
    
    And student = #{age}
    
    </if>
    
    </where>
    
    </select>

    那么这个智能where标签恰到好处的把第一个and给消掉了,从而完成了根据age查询;

    了解以上概念后,我们就把上面的业务给全部写完吧,如果age跟name均不为空,那么我就根据这两个进行查询;

    <select id = "selectAllorbynameAndage" resultType = "Student">
    
    select * from student
    
    <where>
    
    <if test = " name!= null and name!= ' ' ">//如果传过来的student对象有name属性,并且该属性不为空,便执行次条件
    
    And student = #{name}
    
    </if>
    
    <if test = "age !=null and age != ' ' ">
    
    And student = #{age}
    
    </if>
    
    <if test = "age ! = null and age !=' ' And name !=null and name ! = ' ' ">
    
    And student = #{name} And student = #{age}
    
    </if>
    
    </where>
    
    </select>
  • 相关阅读:
    Asp.net MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合 前端javascript数组,后端接受
    jquery each循环遍历完再执行的方法 因为each是异步的 所以要加计数器.
    分布式中的一些概念,分布式简单理解,分布式架构的常见概念
    href="#"与href="javascript:void(0)"的区别
    Newtonsoft.Json高级用法DataContractJsonSerializer,JavaScriptSerializer 和 Json.NET即Newtonsoft.Json datatable,dataset,modle,序列化
    Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串
    C#利用反射实现两个类的对象之间相同属性的值的复制,一个对象的属性复制给另一个对性的属性
    指定文件兼容性模式 < meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />的意义
    使用 IIS 在 Windows 上托管 ASP.NET Core2.0
    jQuery.data() 的实现方式,jQuery16018518865841457738的由来,jQuery后边一串数字的由来
  • 原文地址:https://www.cnblogs.com/StanleyBlogs/p/10772878.html
Copyright © 2011-2022 走看看