精华内容
下载资源
问答
  • 动态SQL

    千次阅读 2021-01-24 16:42:43
    什么是动态SQL动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 官网描述: MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的...

    什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的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
      -------------------------------
    

    我们之前写的 SQL 语句都比较简单,如果有比较复杂的业务,我们需要写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。

    那么怎么去解决这个问题呢?这就要使用 mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。

    搭建环境

    新建一个数据库表:blog

    字段:id,title,author,create_time,views

    CREATE TABLE `blog` (
    `id` varchar(50) NOT NULL COMMENT '博客id',
    `title` varchar(100) NOT NULL COMMENT '博客标题',
    `author` varchar(30) NOT NULL COMMENT '博客作者',
    `create_time` datetime NOT NULL COMMENT '创建时间',
    `views` int(30) NOT NULL COMMENT '浏览量'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    

    4、编写Mapper接口及xml文件

    public interface BlogMapper {
    }
    <?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="com.kuang.mapper.BlogMapper">
    
    </mapper>
    

    5、mybatis核心配置文件,下划线驼峰自动转换

    <settings>
       <setting name="mapUnderscoreToCamelCase" value="true"/>
       <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--注册Mapper.xml-->
    <mappers>
     <mapper resource="mapper/BlogMapper.xml"/>
    </mappers>
    

    6、插入初始数据

    编写接口

    //新增一个博客
    int addBlog(Blog blog);
    

    sql配置文件

    <insert id="addBlog" parameterType="blog">
      insert into blog (id, title, author, create_time, views)
      values (#{id},#{title},#{author},#{createTime},#{views});
    </insert>
    

    初始化博客方法

    @Test
    public void addInitBlog(){
       SqlSession session = MybatisUtils.getSession();
       BlogMapper mapper = session.getMapper(BlogMapper.class);
    
       Blog blog = new Blog();
       blog.setId(IDUtil.genId());
       blog.setTitle("Mybatis如此简单");
       blog.setAuthor("Steve·");
       blog.setCreateTime(new Date());
       blog.setViews(9999);
    
       mapper.addBlog(blog);
    
       blog.setId(IDUtil.genId());
       blog.setTitle("Java如此简单");
       mapper.addBlog(blog);
    
       blog.setId(IDUtil.genId());
       blog.setTitle("Spring如此简单");
       mapper.addBlog(blog);
    
       blog.setId(IDUtil.genId());
       blog.setTitle("微服务如此简单");
       mapper.addBlog(blog);
    
       session.close();
    }
    

    初始化数据完毕!

    if 语句

    需求:根据作者名字和博客名字来查询博客!如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询

    1、编写接口类

    //需求1
    List<Blog> queryBlogIf(Map map);
    

    2、编写SQL语句

    <!--需求1:
    根据作者名字和博客名字来查询博客!
    如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询
    select * from blog where title = #{title} and author = #{author}
    -->
    <select id="queryBlogIf" parameterType="map" resultType="blog">
      select * from blog where
       <if test="title != null">
          title = #{title}
       </if>
       <if test="author != null">
          and author = #{author}
       </if>
    </select>
    

    3、测试

    @Test
    public void testQueryBlogIf(){
       SqlSession session = MybatisUtils.getSession();
       BlogMapper mapper = session.getMapper(BlogMapper.class);
    
       HashMap<String, String> map = new HashMap<String, String>();
       map.put("title","Mybatis如此简单");
       map.put("author","Steve");
       List<Blog> blogs = mapper.queryBlogIf(map);
    
       System.out.println(blogs);
    
       session.close();
    }
    

    这样写我们可以看到,如果 author 等于 null,那么查询语句为 select * from user where title=#{title},但是如果title为空呢?那么查询语句为 select * from user where and author=#{author},这是错误的 SQL 语句,如何解决呢?请看下面的 where 语句!

    Where

    修改上面的SQL语句;

    <select id="queryBlogIf" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <if test="title != null">
              title = #{title}
           </if>
           <if test="author != null">
              and author = #{author}
           </if>
       </where>
    </select>
    

    这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

    Set

    同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,我们怎么处理呢?

    1、编写接口方法

    int updateBlog(Map map);
    

    2、sql配置文件

    <!--注意set是用的逗号隔开-->
    <update id="updateBlog" parameterType="map">
      update blog
         <set>
             <if test="title != null">
                title = #{title},
             </if>
             <if test="author != null">
                author = #{author}
             </if>
         </set>
      where id = #{id};
    </update>
    

    3、测试

    @Test
    public void testUpdateBlog(){
       SqlSession session = MybatisUtils.getSession();
       BlogMapper mapper = session.getMapper(BlogMapper.class);
    
       HashMap<String, String> map = new HashMap<String, String>();
       map.put("title","动态SQL");
       map.put("author","Steve");
       map.put("id","9d6a763f5e1347cebda43e2a32687a77");
    
       mapper.updateBlog(map);
    
    
       session.close();
    }
    

    choose语句

    有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

    1、编写接口方法

    List<Blog> queryBlogChoose(Map map);
    

    2、sql配置文件

    <select id="queryBlogChoose" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <choose>
               <when test="title != null">
                    title = #{title}
               </when>
               <when test="author != null">
                  and author = #{author}
               </when>
               <otherwise>
                  and views = #{views}
               </otherwise>
           </choose>
       </where>
    </select>
    

    3、测试类

    @Test
    public void testQueryBlogChoose(){
       SqlSession session = MybatisUtils.getSession();
       BlogMapper mapper = session.getMapper(BlogMapper.class);
    
       HashMap<String, Object> map = new HashMap<String, Object>();
       map.put("title","Java如此简单");
       map.put("author","Steve");
       map.put("views",9999);
       List<Blog> blogs = mapper.queryBlogChoose(map);
    
       System.out.println(blogs);
    
       session.close();
    }
    

    SQL片段

    有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。

    提取SQL片段:

    <sql id="if-title-author">
       <if test="title != null">
          title = #{title}
       </if>
       <if test="author != null">
          and author = #{author}
       </if>
    </sql>
    

    引用SQL片段:

    <select id="queryBlogIf" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
           <include refid="if-title-author"></include>
           <!-- 在这里还可以引用其他的 sql 片段 -->
       </where>
    </select>
    

    注意:

    ①、最好基于 单表来定义 sql 片段,提高片段的可重用性

    ②、在 sql 片段中不要包括 where

    Foreach

    将数据库中前三个数据的id修改为1,2,3;

    需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

    1、编写接口

    List<Blog> queryBlogForeach(Map map);
    

    2、编写SQL语句

    <select id="queryBlogForeach" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <!--
           collection:指定输入对象中的集合属性
           item:每次遍历生成的对象
           open:开始遍历时的拼接字符串
           close:结束时拼接的字符串
           separator:遍历对象之间需要拼接的字符串
           select * from blog where 1=1 and (id=1 or id=2 or id=3)
         -->
           <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
              id=#{id}
           </foreach>
       </where>
    </select>
    

    3、测试

    @Test
    public void testQueryBlogForeach(){
       SqlSession session = MybatisUtils.getSession();
       BlogMapper mapper = session.getMapper(BlogMapper.class);
    
       HashMap map = new HashMap();
       List<Integer> ids = new ArrayList<Integer>();
       ids.add(1);
       ids.add(2);
       ids.add(3);
       map.put("ids",ids);
    
       List<Blog> blogs = mapper.queryBlogForeach(map);
    
       System.out.println(blogs);
    
       session.close();
    }
    

    小结:其实动态 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态sql 对照着改,防止出错。多在实践中使用才是熟练掌握它的技巧。

    动态SQL在开发中大量的使用,一定要熟练掌握!

    展开全文
  • 详解mybatis动态SQL

    万次阅读 2020-09-10 09:43:19
    什么是动态SQL? 动态 SQL 是 MyBatis 的强大特性之一。顾名思义,就是会动的SQL,即是能够灵活的根据某种条件拼接出完整的SQL语句。这种类似于MySQL中的case when then else then end....这种语法,能够根据某种...

    什么是动态SQL?

    • 动态 SQL 是 MyBatis 的强大特性之一。顾名思义,就是会动的SQL,即是能够灵活的根据某种条件拼接出完整的SQL语句。这种类似于MySQL中的 case when then else then end.... 这种语法,能够根据某种条件动态的拼接出需要的SQL。
    • 至于Mybatis如何实现动态SQL呢,Mybatis提供了非常多的标签,能够让我们在XML文件中灵活的运用这些标签达到拼接SQL的目的。

    常用的标签

    • Mybatis为了能够让开发者灵活的写SQL也是费了一番功夫,定义了很多的标签和语法,下面将会一一介绍。

    if

    • 虽然英文不太好,但是在这么简单的不会不知道是 如果 的意思吧,Java语法中也有,只有判断条件为 true 才会执行其中的SQL语句。
    • 举个栗子:HIS系统中医护人员需要根据特定条件筛选患者,比如住院号,床位,性别等。当然这些条件并不是必填的,具体的功能截图如下:

      1025×60

    • 以上截图中的条件筛选并不是必填的,因此我们不能在SQL中固定,要根据前端是否传值来判断是否需要加上这个条件。那么此时查询语句如何写呢?如下:
    <select id ='selectPats' resultType='com.xxx.domain.PatientInfo'>
      select * from patient_info 
      where status=1
      <!--前端传来的住院号不为null,表示需要根据住院号筛选,此时Where语句就需要加上这个条件-->
      <if test="iptNum!=null">
          and ipt_num=#{iptNum}
      </if>
      
      <!--床位号筛选-->
      <if test="bedNum!=null">
          and bed_num=#{bedNum}
      </if>
    </select>
    
    • <if> 标签中的属性 test 用来指定判断条件,那么问题来了,上面的例子中的 test 中判断条件都是一个条件,如果此时变成两个或者多个条件呢?和SQL的语法类似, and 连接即可,如下:
      <if test="bedNum!=null and bedNum!='' ">
          and bed_num=#{bedNum}
      </if>
    

    choose、when、otherwise

    • 有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
    • 还是上面的例子改变一下:此时只能满足一个筛选条件,如果前端传来住院号就只按照住院号查找,如果传来床位号就只按照床位号筛选,如果什么都没传,就筛选所有在院的。此时的查询如下:
    <select id="selectPats"
         resultType="com.xxx.domain.PatientInfo">
      select * from patient_info where 1=1
      <choose>
        <!--住院号不为null时,根据住院号查找-->
        <when test="iptNum != null">
          AND ipt_num=#{iptNum}
        </when>
        <!--床位号不是NUll-->
        <when test="bedNum != null">
          AND bed_num = #{bedNum}
        </when>
        <otherwise>
          AND status=1
        </otherwise>
      </choose>
    </select>
    
    • MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句, choose 为 switch , when 为 case , otherwise 则为 default 。

    where

    • 举个栗子:对于 choose 标签的例子中的查询,如果去掉 where 后的 1=1 此时的SQL语句会变成什么样子,有三种可能的SQL,如下:
    select * from patient_info where AND ipt_num=#{iptNum};
    
    select * from patient_info where AND bed_num = #{bedNum};
    
    select * from patient_info where AND status=1;
    
    • 发生了什么,以上三条SQL语句对吗?很显然是不对的,显然 where 后面多了个 AND 。如何解决呢?此时就要用到 where 这个标签了。
    • where 元素只会在子元素返回任何内容的情况下才插入 WHERE 子句。而且,若子句的开头为 AND 或 OR , where 元素也会将它们去除。
    • 此时的查询改造如下:
    <select id="selectPats"
         resultType="com.xxx.domain.PatientInfo">
      select * from patient_info
        <where>
            <choose>
              <!--住院号不为null时,根据住院号查找-->
              <when test="iptNum != null">
                AND ipt_num=#{iptNum}
              </when>
              <!--床位号不是NUll-->
              <when test="bedNum != null">
                AND bed_num = #{bedNum}
              </when>
              <otherwise>
                AND status=1
              </otherwise>
            </choose>
       </where>
    </select>
    

    foreach

    • foreach 是用来对集合的遍历,这个和Java中的功能很类似。通常处理SQL中的 in 语句。
    • foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项( item )和索引( index )变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符
    • 你可以将任何可迭代对象(如 List 、 Set 等)、 Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时, index 是当前迭代的序号, item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时, index 是键, item 是值。
    • 例子如下:
    <select id="selectPats" resultType="com.xxx.domain.PatientInfo">
      SELECT *
      FROM patient_info 
      WHERE ID in
      <foreach item="item" index="index" collection="list"
          open="(" separator="," close=")">
            #{item}
      </foreach>
    </select>
    
    • 改标签中的各个属性的含义如下:
    属性含义
    item表示在迭代过程中每一个元素的别名
    index表示在迭代过程中每次迭代到的位置(下标)
    open前缀
    close后缀
    separator分隔符,表示迭代时每个元素之间以什么分隔

    set

    • 讲这个标签之前,先看下面这个例子:
    <update id="updateStudent" parameterType="Object">
        UPDATE STUDENT
        SET NAME = #{name},
        MAJOR = #{major},
        HOBBY = #{hobby}
        WHERE ID = #{id};
    </update>
    
    <update id="updateStudent" parameterType="Object">
        UPDATE STUDENT SET
        <if test="name!=null and name!='' ">
            NAME = #{name},
        </if>
        <if test="hobby!=null and hobby!='' ">
            MAJOR = #{major},
        </if>
        <if test="hobby!=null and hobby!='' ">
            HOBBY = #{hobby}
        </if>
        WHERE ID = #{id};
    </update>
    
    • 上面的例子中没有使用 if 标签时,如果有一个参数为 null ,都会导致错误。当在 update 语句中使用 if 标签时,如果最后的 if 没有执行,则或导致逗号多余错误。使用 set 标签可以将动态的配置 set 关键字,和剔除追加到条件末尾的任何不相关的逗号。
    • 使用 set+if 标签修改后,如果某项为 null 则不进行更新,而是保持数据库原值。此时的查询如下:
    <update id="updateStudent" parameterType="Object">
        UPDATE STUDENT
        <set>
            <if test="name!=null and name!='' ">
                NAME = #{name},
            </if>
            <if test="hobby!=null and hobby!='' ">
                MAJOR = #{major},
            </if>
            <if test="hobby!=null and hobby!='' ">
                HOBBY = #{hobby}
            </if>
        </set>
        WHERE ID = #{id};
    </update>
    

    sql

    • 在实际开发中会遇到许多相同的SQL,比如根据某个条件筛选,这个筛选很多地方都能用到,我们可以将其抽取出来成为一个公用的部分,这样修改也方便,一旦出现了错误,只需要改这一处便能处处生效了,此时就用到了 <sql> 这个标签了。
    • 当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求 <select> 结构清晰也可将 sql 语句分解。如下:
    <!-- 查询字段 -->
    <sql id="Base_Column_List">
        ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
    </sql>
    
    <!-- 查询条件 -->
    <sql id="Example_Where_Clause">
        where 1=1
        <trim suffixOverrides=",">
            <if test="id != null and id !=''">
                and id = #{id}
            </if>
            <if test="major != null and major != ''">
                and MAJOR = #{major}
            </if>
            <if test="birthday != null ">
                and BIRTHDAY = #{birthday}
            </if>
            <if test="age != null ">
                and AGE = #{age}
            </if>
            <if test="name != null and name != ''">
                and NAME = #{name}
            </if>
            <if test="hobby != null and hobby != ''">
                and HOBBY = #{hobby}
            </if>
        </trim>
    </sql>
    

    include

    • 这个标签和 <sql> 是天仙配,是共生的, include 用于引用 sql 标签定义的常量。比如引用上面sql标签定义的常量,如下:
    <select id="selectAll" resultMap="BaseResultMap">
        SELECT
        <include refid="Base_Column_List" />
        FROM student
        <include refid="Example_Where_Clause" />
    </select>
    
    • refid 这个属性就是指定 <sql> 标签中的 id 值(唯一标识)。

    总结

    • 至此,Mybatis动态SQL中常用的标签就已经介绍完了,这部分的内容在实际工作中是必须会用到的,除非你们公司不用Mybatis。

    拓展一下

    • 前面介绍了动态SQL的一些标签以及属性,相信看完之后应该能够灵活的应用了,但是在实际开发中还是有一些奇技淫巧的,陈某今天简单的讲几个。

    Mybatis中如何避免魔数

    • 开过阿里巴巴开发手册的大概都知道代码中是不允许出现 魔数 的,何为 魔数 ?简单的说就是一个数字,一个只有你知道,别人不知道这个代表什么意思的数字。通常我们在Java代码中都会定义一个常量类专门定义这些数字。
    • 比如获取医生和护士的权限,但是医生和护士的权限都不相同,在这条SQL中肯定需要根据登录的类型 type 来区分,比如 type=1 是医生, type=2 是护士,估计一般人会这样写:
    <if test="type!=null and type==1">
        -- ....获取医生的权限
    </if>
    
    <if test="type!=null and type==2">
        -- ....获取护士的权限
    </if>
    
    • 这样写也没什么错,但是一旦这个 type 代表的含义变了,那你是不是涉及到的SQL都要改一遍。
    • 开发中通常定义一个常量类,如下:
    package com.xxx.core.Constants;
    public class CommonConstants{
      //医生
      public final static int DOC_TYPE=1;
      
      //护士
      public final static int NUR_TYPE=2;
      
    }
    
    • 那么此时的SQL应该如何写呢?如下:
    <if test="type!=null and type==@com.xxx.core.Constants.CommonConstants@DOC_TYPE">
        -- ....获取医生的权限
    </if>
    
    <if test="type!=null and type==@com.xxx.core.Constants.CommonConstants@NUR_TYPE">
        -- ....获取护士的权限
    </if>
    
    • 就是这么简单,就是 @ + 全类名 + @ + 常量 。
    • 除了调用常量类中的常量,还可以类中的方法,很少用到,不再介绍了,感兴趣的可以问下度娘。

    如何引用其他XML中的SQL片段

    • 实际开发中你可能遇到一个问题,比如这个 resultMap 或者这个 <sql> 片段已经在另外一个 xxxMapper.xml 中已经定义过了,此时当前的xml还需要用到,难不成我复制一份?小白什么也不问上来就复制了,好吧,后期修改来了,每个地方都需要修改了。难受不?
    • 其实Mybatis中也是支持引用其他Mapper文件中的SQL片段的。其实很简单,比如你在 com.xxx.dao.xxMapper 这个Mapper的XML中定义了一个SQL片段如下:
    <sql id="Base_Column_List">
        ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
    </sql>
    
    • 此时我在 com.xxx.dao.PatinetMapper 中的XML文件中需要引用,如下:
      <include refid="com.xxx.dao.xxMapper.Base_Column_List"></include>
    
    • 如此简单,类似于Java中的全类名。
    • <select> 标签中的 resultMap 同样可以这么引用,和上面引用的方式一样,不再赘述了。原文:
    展开全文
  • 1.Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理? 1.动态SQL的概念 ​ 动态sql是指在进行sql操作的时候,传入的参数对象或者参数值,根据匹配的条件,有可能需要动态的去判断是否为空,...

    1.Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理?

    1.动态SQL的概念

    ​ 动态sql是指在进行sql操作的时候,传入的参数对象或者参数值,根据匹配的条件,有可能需要动态的去判断是否为空,循环,拼接等情况;

    2.动态Sql的标签大致有以下几种
    if 和 where 标签和include标签

    ​ if标签中可以判断传入的值是否符合某种规则,比如是否不为空;

    ​ where标签可以用来做动态拼接查询条件,当和if标签配合的时候,不用显示的声明类似where 1=1这种无用的条件,来达到匹配的时候and会多余的情况;

    ​ include可以把大量重复的代码整理起来,当使用的时候直接include即可,减少重复代码的编写

    <!--动态Sql : where / if-->
    <select id="findUserById"  resultType="com.lagou.pojo.User">
      select <include refid="userInfo"/> from user
      <where>
        <if test="id != null and id != 0">
          AND id = #{id}
        </if>
        <if test="name != null and name != ''">
          AND name = #{name}
        </if>
      </where>
    </select>
    
    choose、when、otherwise 标签

    ​ 类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件

    <!--动态Sql: choose、when、otherwise 标签-->
    <select id="findUserById" resultType="com.lagou.pojo.User">
      select * from user
      <where>
        <choose>
          <when test="name != null and name != ''">
            AND name = #{name}
          </when>
          <otherwise>
            AND id = #{id}
          </otherwise>
        </choose>
      </where>
    </select>
    

    foreach 标签

    ​ foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中,里面涉及到 item(具体的每一个对象), index(序号), open(开始符), close(结束符), separator(分隔符)

    <!--动态Sql: foreach标签, 批量插入-->
    <insert id="insertBatch" useGeneratedKeys="true" keyProperty="id">
      insert into user (id, name)
      values
      <foreach collection="list" item="user" separator="," >
        (#{user.id}, #{user.name})
      </foreach>
    </insert>
    
    <!--动态Sql: foreach标签, in查询-->
    <select id="dynamicSqlSelectList" resultType="com.lagou.pojo.User">
      SELECT * from user WHERE id in
      <foreach collection="list" item="id" open="(" close=")" separator="," >
        #{id}
      </foreach>
    </select>
    

    map参数

    ​ < map> 标签需要结合MyBatis的参数注解 @Param()来使用,需要告诉Mybatis配置文件中的collection="map"里的map是一个参数

    <!--动态Sql: foreach标签, map参数查询-->
    <select id="findByMap" resultType="com.lagou.pojo.User">
      select * from user WHERE
      <foreach collection="map" index="key" item="value"  separator="=">
        ${key} = #{value}
      </foreach>
    </select>
    

    set标签

    ​ 适用于更新中,当匹配某个条件后,才会对该字段进行更新操作

    <!--动态Sql: set 标签-->
    <update id="updateSet" parameterType="com.lagou.pojo.User">
      update user
      <set>
        <if test="name != null and name != ''">
          name = #{name},
        </if>
      </set>
      where id = #{id}
    </update>
    
    trim标签

    是一个格式化标签,主要有4个参数:

    prefix(前缀)

    prefixOverrides(去掉第一个标记)

    suffix(后缀)

    suffixOverrides(去掉最后一个标记)

    <!--动态Sql: trim 标签-->
    <select id="findUser" resultType="com.lagou.pojo.User">
      select * from user
      <trim prefix="where" suffix="order by id" prefixOverrides="and | or" suffixOverrides=",">
        <if test="name != null and name != ''">
          AND name = #{name}
        </if>
        <if test="id != null">
          AND id = #{id}
        </if>
      </trim>
    </select>
    
    3.动态sql的执行原理
    • 首先在解析xml配置文件的时候,会有一个SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass) 的操作
    • createSqlSource底层使用了XMLScriptBuilder来对xml中的标签进行解析
    • XMLScriptBuilder调用了parseScriptNode()的方法,
    • 在parseScriptNode()的方法中有一个parseDynamicTags()方法,会对nodeHandlers里的标签根据不同的handler来处理不同的标签
    • 然后把DynamicContext结果放回SqlSource中
    • DynamicSqlSource获取BoundSql
    • 在Executor执行的时候,调用DynamicSqlSource的解析方法,并返回解析好的BoundSql,和已经排好序,需要替换的参数
      在这里插入图片描述
      在这里插入图片描述

    ​ 简单的说:就是使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql

    展开全文
  • SQLServer 执行动态SQL语句

    千次阅读 2019-09-22 17:04:38
    执行动态SQL语句 首先定义变量 @Games 为运动会名称, 为动态SQL语句定义变量 然后建立动态的SQL语句 最后运行这个动态的SQL语句 EXEC (@SQL2) 或 Exec SP_ExecuteSQL @SQL2 -- 执行动态SQL语句示例,复制后可直接...

    执行动态SQL语句

    首先定义变量 @Games 为运动会名称,
    为动态SQL语句定义变量
    然后建立动态的SQL语句
    最后运行这个动态的SQL语句 EXEC (@SQL2) 或 Exec SP_ExecuteSQL @SQL2

    -- 执行动态SQL语句示例,复制后可直接运行,运行过程中执行SQL3的语句会出错
    DECLARE @Games VARCHAR(20)
    DECLARE @NUM   SMALLINT
    DECLARE @STR   NVARCHAR(4000)
    DECLARE @SQL1  NVARCHAR(4000)    -- 第1种数据类型
    DECLARE @SQL2  NVARCHAR(4000)    -- 第1种数据类型
    DECLARE @SQL3  VARCHAR(4000)     -- 第2种数据类型
    
    SELECT @Games = Games FROM (SELECT '市全运会' Games) A
    
    -- 设置相同的SQL语句
    SET @STR = 'WITH Team (Games,GroupType,SEX,Team) AS ('
    SET @STR = @STR + ' SELECT ''市全运会'',''高中组'',''男'',''100米'' UNION ALL'
    SET @STR = @STR + ' SELECT ''市全运会'',''高中组'',''女'',''100米'' UNION ALL'
    SET @STR = @STR + ' SELECT ''市全运会'',''初中组'',''男'',''100米'' UNION ALL'
    SET @STR = @STR + ' SELECT ''市全运会'',''初中组'',''女'',''100米'' )'
    
    SET @SQL1 = @STR + ' SELECT @A=COUNT(*) FROM Team WHERE SEX = ''女'''
    SET @SQL2 = @STR + ' SELECT Games,GroupType,SEX,Team FROM Team WHERE Games = ''' + @Games + ''''
    SET @SQL3 = @SQL2
    
    EXEC (@SQL2)    -- 执行动态SQL成功
    EXEC (@SQL3)    -- 执行动态SQL成功
    
    Exec SP_ExecuteSQL @SQL2     -- 执行动态SQL成功
    Exec SP_ExecuteSQL @SQL3     -- 执行动态SQL出错 显示错误信息为:需要类型为 'ntext/nchar/nvarchar' 的参数
    
    Exec SP_ExecuteSQL @SQL1,N'@A INT Output',@num Output  -- 成功将动态SQL语句的运行结果保存在变量@NUM中
    SELECT @NUM
    
    展开全文
  • MyBatis 动态 SQL

    千次阅读 2020-08-04 17:20:59
    MyBatis 令人喜欢的一大特性就是动态 SQL。在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的。MyBatis 动态 SQL 的出现, 解决了这个麻烦。 MyBatis通过 OGNL 来进行动态 SQL 的使用的。目前...
  • 【Mybatis】动态SQL 实例

    万次阅读 2021-07-02 20:58:01
    动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用...
  • MyBatis 动态SQL

    千次阅读 热门讨论 2021-03-19 14:51:37
    MyBatis 动态SQL Mybatis的强大特性之一便是它的动态SQL。 利用动态SQL可以解决根据不同条件拼接SQL语句这一问题,如果你有过JDBC或其他类似框架的经验,你就能体会到这种根据不同条件拼接 SQL 语句有多么麻烦,拼接...
  • Mybatis动态SQL的实现

    万次阅读 多人点赞 2019-02-27 19:28:42
    Mybatis提供了动态SQL,也就是可以根据用户提供的参数,动态决定查询语句依赖的查询条件或SQL语句的内容。 动态SQL标签 if 和 where 标签 &amp;lt;!--动态Sql : where / if--&amp;gt; &amp;lt;select ...
  • SQL Server 动态SQL拼接

    千次阅读 2019-03-31 22:54:38
    在多添加搜索数据时,大多会使用到动态SQL搜索,当搜索栏目中存在string,Guid,decimal等类型数据时,要注意拼接时数据类型转换,方法如下: 方法一:使用 SQL Server中的存储过程(StoredProcedure),在存储过程...
  • SQLServer动态SQL语句的用法
  • Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能。 Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | ...
  • Mybatis——动态sql

    千次阅读 多人点赞 2020-12-24 23:13:53
    动态sql 1.同一个dao的方法,根据不同的条件表示不同的sql语句,主要是where部分有变化; 2.使用mybatis提供的标签,实现动态sql能力,主要使用如 if, where, foreach, sql; 3.使用动态sql的时候,dao方法的形参使用...
  • 动态SQL 和静态SQL 的 区别

    千次阅读 2018-08-20 11:24:57
    所谓SQL的静态和动态,是指SQL语句在何时被编译和执行,二者都是用在SQL嵌入式编程中的,这里所说的嵌入式是指将SQL语句嵌入在高级语言中,而不是针对于单片机的那种嵌入式编程...嵌入式动态SQL应用需要预编译,非嵌...
  • Postgresql动态SQL

    千次阅读 2018-03-26 00:57:36
    PostgreSQL支持动态SQL,以PL/Pgsql为例,语法如下:EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ];上式中的可选项target表示a record variable, a row variable, or a comma-...
  • MyBatis基础用法--动态SQL

    万次阅读 2017-10-05 19:07:34
    动态 SQL简介 if choose, when, otherwise trim, where, set foreach _parameter、_databaseId bind sql、include 动态 SQL简介 MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似...
  • hibernate实现动态SQL查询,通过XML配置SQL,FREEMARKER 解析,生成要执行的SQL
  • T-SQL动态查询(4)——动态SQL

    万次阅读 2015-12-09 09:38:17
    接上文:T-SQL动态查询(3)——静态SQL 前言: 前面说了很多关于动态查询的内容,本文将介绍使用动态SQL解决动态查询的一些方法。 为什么使用动态SQL: 在很多项目中,动态SQL被广泛使用甚至滥用,很多时候,动态...
  • MyBatis官方文档-动态 SQL

    千次阅读 2019-09-16 14:49:04
    动态 SQL MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个...
  • 目录动态SQLiftrim (where, set)choose (when, otherwise)SQL片段foreach...动态SQL if choose (when, otherwise) trim (where, set) foreach 数据表 CREATE TABLE `blog` ( `id` VARCHAR(50) NOT NULL COMMENT '博
  • 动态SQL与绑定变量

    2013-04-24 20:39:22
    动态SQL与绑定变量 动态SQL与绑定变量
  • iBatis 动态SQL (Dynamic SQL)

    千次阅读 2017-10-31 13:19:22
    ibatis 动态SQL Dynamic SQL
  • SSM第五讲 动态SQL与高级查询

    万次阅读 2020-08-17 21:26:49
    动态SQL与高级查询 动态sql 高级查询 一. 动态SQL(重点) 1. 动态SQL是什么 就是相对与固定SQL。就是通过传入的参数不一样,可以组成不同结构的SQL语句. 这种根据参数的条件修改SQL结构的SQL语句,我们称为动态SQL...
  • Oracle 动态SQL

    千次阅读 2013-09-06 11:15:46
    Oracle 动态SQL 一、动态SQL的简介 1、定义 静态SQL是指直接嵌入到PL/SQL块中的SQL语句。 动态SQL是指运行PL/SQL块是动态输入的SQL语句。 2、适用范围 如果在PL/SQL块中需要执行DDL语句(create,alter,drop等)、DCL...
  • Mybatis 动态 SQL ,可以让我们在 XML 映射文件内,以 XML 标签的形 式编写动态 SQL ,完成逻辑判断和动态拼接 SQL 的功能。 Mybatis 提供了 9 种动态 SQL 标签:<if/>、<choose/>、<when/>...
  • Mybatis的动态SQL语句

    千次阅读 多人点赞 2021-02-12 21:16:03
    Mybatis的动态SQL语句项目目录动态 SQL 之if标签持久层 Dao 接口持久层 Dao 映射配置测试代码动态 SQL 之where标签持久层 Dao 映射配置动态 SQL 之foreach标签需求在 QueryVo 中加入一个 List 集合用于封装参数持久...
  • sqlserver 动态sql的执行,有两个方法execute和 sp_executesql.其中第一个方法execute可以简写为exec. execute方法适合执行没有返回值的动态sql,sp_executesql可以获取到动态sql的返回值.二者比较起来,前者写起来简单...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 461,853
精华内容 184,741
关键字:

动态sql