MyBatis 动态 SQL 最全教程,这样写 SQL 太优雅了!

这篇具有很好参考价值的文章主要介绍了MyBatis 动态 SQL 最全教程,这样写 SQL 太优雅了!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、MyBatis动态 sql 是什么

动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。

例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态 SQL 恰好解决了这一问题,可以根据场景动态的构建查询。

动态SQL(code that is executed dynamically),它一般是根据用户输入或外部条件动态组合的SQL语句块。 动态SQL能灵活的发挥SQL强大的功能、方便的解决一些其它方法难以解决的问题。 相信使用过动态SQL的人都能体会到它带来的便利,然而动态SQL有时候在执行性能 (效率)上面不如静态SQL,而且使用不恰当,往往会在安全方面存在隐患 (SQL 注入式攻击)。

1.Mybatis 动态 sql 是做什么的?

Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。

2.Mybatis 的 9 种 动 态 sql 标 签有哪些?

MyBatis 动态 SQL 最全教程,这样写 SQL 太优雅了!

3.动态 sql 的执行原理?

原理为:使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

二、MyBatis标签

1.if标签:条件判断

MyBatis if 类似于 Java 中的 if 语句,是 MyBatis 中最常用的判断语句。使用 if 标签可以节省许多拼接 SQL 的工作,把精力集中在 XML 的维护上。

1)不使用动态sql

<select id="selectUserByUsernameAndSex"
        resultType="user" parameterType="com.ys.po.User">
    <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面          不一定要写id,
         写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 -->
    select * from user where username=#{username} and sex=#{sex}
</select>

if 语句使用方法简单,常常与 test 属性联合使用。语法如下:

<if test="判断条件">    SQL语句</if>

2)使用动态sql

上面的查询语句,我们可以发现,如果 #{username} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断,可多个 if 语句同时使用。

以下语句表示为可以按照网站名称(name)或者网址(url)进行模糊查询。如果您不输入名称或网址,则返回所有的网站记录。但是,如果你传递了任意一个参数,它就会返回与给定参数相匹配的记录。

<select id="selectAllWebsite" resultMap="myResult">  
    select id,name,url from website 
    where 1=1    
   <if test="name != null">        
       AND name like #{name}   
   </if>    
   <if test="url!= null">        
       AND url like #{url}    
   </if>
</select>

2.where+if标签

where、if同时使用可以进行查询、模糊查询

注意,<if>失败后, <where> 关键字只会去掉库表字段赋值前面的and,不会去掉语句后面的and关键字,即注意,<where> 只会去掉<if> 语句中的最开始的and关键字。所以下面的形式是不可取的

<select id="findQuery" resultType="Student">
    <include refid="selectvp"/>
    <where>
        <if test="sacc != null">
            sacc like concat('%' #{sacc} '%')
        </if>
        <if test="sname != null">
            AND sname like concat('%' #{sname} '%')
        </if>
        <if test="sex != null">
            AND sex=#{sex}
        </if>
        <if test="phone != null">
            AND phone=#{phone}
        </if>
    </where>
</select>

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

3.set标签

set可以用来修改

<update id="upd">
    update student
    <set>
        <if test="sname != null">sname=#{sname},</if>
        <if test="spwd != null">spwd=#{spwd},</if>
        <if test="sex != null">sex=#{sex},</if>
        <if test="phone != null">phone=#{phone}</if>
    sid=#{sid}
    </set>
    where sid=#{sid}
</update>

4.choose(when,otherwise) 语句

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

<select id="selectUserByChoose" resultType="com.ys.po.User" parameterType="com.ys.po.User">
      select * from user
      <where>
          <choose>
              <when test="id !='' and id != null">
                  id=#{id}
              </when>
              <when test="username !='' and username != null">
                  and username=#{username}
              </when>
              <otherwise>
                  and sex=#{sex}
              </otherwise>
          </choose>
      </where>
  </select>

也就是说,这里我们有三个条件,id、username、sex,只能选择一个作为查询条件

  • 如果 id 不为空,那么查询语句为:select * from user where id=?
  • 如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;
  • 如果 username 为空,那么查询语句为 select * from user where sex=?

5.trim

trim标记是一个格式化的标记,可以完成set或者是where标记的功能

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

①、用 trim 改写上面第二点的 if+where 语句

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ys.po.User">
    select * from user
    <!-- <where>
        <if test="username != null">
           username=#{username}
        </if>
         
        <if test="username != null">
           and sex=#{sex}
        </if>
    </where>  -->
    <trim prefix="where" prefixOverrides="and | or">
        <if test="username != null">
           and username=#{username}
        </if>
        <if test="sex != null">
           and sex=#{sex}
        </if>
    </trim>
</select>
  • prefix:前缀
  • prefixoverride:去掉第一个and或者是or

②、用 trim 改写上面第三点的 if+set 语句

<!-- 根据 id 更新 user 表的数据 -->
<update id="updateUserById" parameterType="com.ys.po.User">
    update user u
        <!-- <set>
            <if test="username != null and username != ''">
                u.username = #{username},
            </if>
            <if test="sex != null and sex != ''">
                u.sex = #{sex}
            </if>
        </set> -->
        <trim prefix="set" suffixOverrides=",">
            <if test="username != null and username != ''">
                u.username = #{username},
            </if>
            <if test="sex != null and sex != ''">
                u.sex = #{sex},
            </if>
        </trim>
     
     where id=#{id}
</update>
  • suffix:后缀
  • suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

③、trim+if同时使用可以添加

<insert id="add">
    insert  into student
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="sname != null">sname,</if>
        <if test="spwd != null">spwd,</if>
        <if test="sex != null">sex,</if>
        <if test="phone != null">phone,</if>
    </trim>

    <trim prefix="values (" suffix=")"  suffixOverrides=",">
        <if test="sname != null">#{sname},</if>
        <if test="spwd != null">#{spwd},</if>
        <if test="sex != null">#{sex},</if>
        <if test="phone != null">#{phone}</if>
    </trim>

</insert>

6.MyBatis foreach标签

foreach是用来对集合的遍历,这个和Java中的功能很类似。通常处理SQL中的in语句。

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符

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

//批量查询
<select id="findAll" resultType="Student" parameterType="Integer">
    <include refid="selectvp"/> WHERE sid in
    <foreach item="ids" collection="array"  open="(" separator="," close=")">
        #{ids}
    </foreach>
</select>
//批量删除
<delete id="del"  parameterType="Integer">
    delete  from  student  where  sid in
    <foreach item="ids" collection="array"  open="(" separator="," close=")">
        #{ids}
    </foreach>
</delete>
整合案例

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="com.yzx.mapper.StuMapper">
    <sql id="selectvp">
        select  *  from  student
    </sql>
    
    <select id="find" resultType="Student">
        <include refid="selectvp"/>
    </select>

    <select id="findbyid"  resultType="student">
        <include refid="selectvp"/>
        WHERE 1=1
        <if test="sid != null">
            AND sid like #{sid}
        </if>
    </select>

        <select id="findQuery" resultType="Student">
            <include refid="selectvp"/>
            <where>
                <if test="sacc != null">
                    sacc like concat('%' #{sacc} '%')
                </if>
                <if test="sname != null">
                    AND sname like concat('%' #{sname} '%')
                </if>
                <if test="sex != null">
                    AND sex=#{sex}
                </if>
                <if test="phone != null">
                    AND phone=#{phone}
                </if>
            </where>
        </select>

    <update id="upd">
        update student
        <set>
            <if test="sname != null">sname=#{sname},</if>
            <if test="spwd != null">spwd=#{spwd},</if>
            <if test="sex != null">sex=#{sex},</if>
            <if test="phone != null">phone=#{phone}</if>
        sid=#{sid}
        </set>
        where sid=#{sid}
    </update>

    <insert id="add">
        insert  into student
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="sname != null">sname,</if>
            <if test="spwd != null">spwd,</if>
            <if test="sex != null">sex,</if>
            <if test="phone != null">phone,</if>
        </trim>

        <trim prefix="values (" suffix=")"  suffixOverrides=",">
            <if test="sname != null">#{sname},</if>
            <if test="spwd != null">#{spwd},</if>
            <if test="sex != null">#{sex},</if>
            <if test="phone != null">#{phone}</if>
        </trim>

    </insert>
    <select id="findAll" resultType="Student" parameterType="Integer">
        <include refid="selectvp"/> WHERE sid in
        <foreach item="ids" collection="array"  open="(" separator="," close=")">
            #{ids}
        </foreach>
    </select>

    <delete id="del"  parameterType="Integer">
        delete  from  student  where  sid in
        <foreach item="ids" collection="array"  open="(" separator="," close=")">
            #{ids}
        </foreach>
    </delete>



</mapper>

测试类:

package com.yzx.test;

import com.yzx.entity.Student;
import com.yzx.mapper.StuMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class StuTest {
    SqlSession sqlSession=null;
    InputStream is=null;

    @Before
    public   void  before() throws IOException {
        //1.读取核心配置文件
        is= Resources.getResourceAsStream("sqlMapperConfig.xml");
        //2.拿到工厂构建类
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        //3.拿到具体工厂
        SqlSessionFactory build=sqlSessionFactoryBuilder.build(is);
        //4.拿到session
        sqlSession = build.openSession();
    }

    @After
    public  void  after(){
        //7,提交事务
        sqlSession.commit();
        //8.关闭资源
        sqlSession.close();
        if(is!=null){
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        };
    }

    //查询所有
    @Test
    public  void  find(){
        //5.获取具体的mapper接口
        StuMapper mapper=sqlSession.getMapper(StuMapper.class);
        //6.调用执行
        List<Student> list=mapper.find();
        list.forEach(a-> System.out.println(a));
    }
    //查询单个
    @Test
    public  void  findbyid(){

        StuMapper mapper=sqlSession.getMapper(StuMapper.class);
        List<Student> list=mapper.findbyid(2);
        list.forEach(a-> System.out.println(a));
    }
    //模糊查询
    @Test
    public  void  findQuery(){

        StuMapper mapper=sqlSession.getMapper(StuMapper.class);

        Student  stu=new Student();
        stu.setSname("小");
        stu.setSex("男");
        List<Student> list=mapper.findQuery(stu);
        list.forEach(a-> System.out.println(a));
    }
    //修改
    @Test
    public  void  upd(){

        StuMapper mapper=sqlSession.getMapper(StuMapper.class);

        Student  stu=new Student();
        stu.setSid(3);
        stu.setSname("小若");
        stu.setSex("人妖");
        int i=mapper.upd(stu);
        System.out.println("修改了"+i+"条数据"+"  "+stu.toString());

    }
    //添加
    @Test
    public  void  add(){

        StuMapper mapper=sqlSession.getMapper(StuMapper.class);

        Student  stu=new Student();
        stu.setSname("小贺");
        stu.setSex("男");
        stu.setPhone("99999999");
        int i=mapper.add(stu);
        System.out.println("添加了"+i+"条数据"+"  "+stu.toString());

    }

    //批量操作
    @Test
    public  void  findAll(){

        StuMapper mapper=sqlSession.getMapper(StuMapper.class);
        Integer[] i={1,2,3,4};
        List<Student> list=mapper.findAll(i);
        list.forEach(a-> System.out.println(a));
    }
    //批量操作

    //批量删除
    @Test
    public  void  del(){
        StuMapper mapper=sqlSession.getMapper(StuMapper.class);
        Integer[] i={1,2,3,4};
        int i1=mapper.del(i);
        System.out.println("删除了"+i1+"条数据");
    }
}

7.sql

在实际开发中会遇到许多相同的SQL,比如根据某个条件筛选,这个筛选很多地方都能用到,我们可以将其抽取出来成为一个公用的部分,这样修改也方便,一旦出现了错误,只需要改这一处便能处处生效了,此时就用到了<sql>这个标签了。

当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求<select>结构清晰也可将 sql 语句分解。

<sql id="selectvp">
    select  *  from  student
</sql>

8.include

这个标签和<sql>是天仙配,是共生的,include用于引用sql标签定义的常量。比如引用上面sql标签定义的常量

refid这个属性就是指定<sql>标签中的id值(唯一标识)

<select id="findbyid"  resultType="student">
    <include refid="selectvp"/>
    WHERE 1=1
    <if test="sid != null">
        AND sid like #{sid}
    </if>
</select>

9.如何引用其他XML中的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>

三、MyBatis关联查询

1.MyBatis一对多关联查询

<!--一对多-->
<resultMap id="myStudent1" type="student1">
    <id property="sid" column="sid"/>
    <result property="sname" column="sname"/>
    <result property="sex" column="sex"/>
    <result property="sage" column="sage"/>
    <collection property="list" ofType="teacher">
        <id property="tid" column="tid"/>
        <result property="tname" column="tname"/>
        <result property="tage" column="tage"/>
    </collection>
</resultMap>

<!--一对多-->
<select id="find1" resultMap="myStudent1">
    select  *  from  student1  s  left  join  teacher  t  on s.sid=t.sid
</select>

2.MyBatis多对一关联查询

<!--多对一-->
<resultMap id="myTeacher" type="teacher">
    <id property="tid" column="tid"/>
    <result property="tname" column="tname"/>
    <result property="tage" column="tage"/>
    <association property="student1" javaType="Student1">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <result property="sex" column="sex"/>
        <result property="sage" column="sage"/>
    </association>
</resultMap>


<!--多对一-->
<select id="find2" resultMap="myTeacher">
select  *  from  teacher  t right join student1 s on  t.sid=s.sid
</select>

3.MyBatis多对多关联查询

<!--多对多 以谁为主表查询的时候,主表约等于1的一方,另一方相当于多的一方-->
<select id="find3" resultMap="myStudent1">
    select  *  from  student1 s  left join relevance r on  s.sid=r.sid  left join teacher t on  r.tid=t.tid
</select>

版权声明:本文为CSDN博主「变成秃头怪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/SGLP521/article/details/121509714

更多文章推荐:

1.Spring Boot 3.x 教程,太全了!

2.2,000+ 道 Java面试题及答案整理(2024最新版)

3.免费获取 IDEA 激活码的 7 种方式(2024最新版)

觉得不错,别忘了随手点赞+转发哦!文章来源地址https://www.toymoban.com/news/detail-858669.html

到了这里,关于MyBatis 动态 SQL 最全教程,这样写 SQL 太优雅了!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 干掉 NullPointerException,这样写优雅!

    来源:blog.csdn.net/zjhred/article/details/84976734 在文章的开头,先说下NPE问题,NPE问题就是,我们在开发中经常碰到的NullPointerException。假设我们有两个类,他们的UML类图如下图所示 在这种情况下,有如下代码: 这种写法,在user为null时,是有可能报NullPointerException异常的。为了解

    2024年02月13日
    浏览(25)
  • mybatis----动态Sql

    1.if标签 通过if标签构建动态条件,通过其test属性的true或false来判断该添加语句是否执行。 mapper接口 映射文件 这里test中的属性名与Account类中的属性名一致。例如:上述文件的第一个if标签中的id严格与Account中属性名id一致。 测试 结果: 执行效果等同于select * from account whe

    2024年01月23日
    浏览(42)
  • MyBatis:动态 SQL 标签

    MyBatis 动态 SQL 标签 ,是一组预定义的标签,用于构建动态的 SQL 语句,允许在 SQL 语句中使用条件、循环和迭代等逻辑。通过使用动态 SQL 标签,开发者可以根据不同的条件和参数生成不同的 SQL 语句,实现更加灵活的数据访问操作。但是,需要谨慎处理 SQL 注入问题,确保所

    2024年02月04日
    浏览(45)
  • MyBatis之动态sql

    目录 一、MyBatis动态sql 1.1 是什么 1.2 作用 1.3 优点 1.4 特殊标签 1.5 代码演示 二、#和$的区别 2.1 #使用 2.2 $使用 2.3 综合 2.4 代码演示 三、resultType与resultMap的区别 3.1 关于resultType 3.2 关于resultMap   3.3 两者区别 3.4 代码演示 是一种在SQL语句中根据不同条件动态拼接SQL的方式。通

    2024年02月11日
    浏览(34)
  • MyBatis - 动态 SQL

    动态 SQL 是 MyBatis 提供的一个非常强大的功能,它可以让我们在运行时构建 SQL 语句。这意味着我们可以根据应用程序的需求来构建符合要求的 SQL。通常情况下,这是非常有用的,因为有时我们不知道要查询哪些表,或者要查询哪些列。此外,动态 SQL 还可以用来构建动态修改

    2024年02月07日
    浏览(48)
  • MyBatis 实现动态 SQL

     MyBatis 中的动态 SQL 就是 SQL语句可以根据不同的情况情况来拼接不同的sql。 本文会介绍 xml 和 注解 两种方式的动态SQL实现方式。 先创建一个数据表,SQL代码如下: 数据库表和JAVA对象的对应如下:   平时在注册账号时会有一些非必填项,而我们就可以使用 if 标签来跟据条

    2024年02月19日
    浏览(47)
  • 【MyBatis】动态SQL

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

    2024年01月17日
    浏览(42)
  • Mybatis-动态SQL

    Mabits是一个Java持久化框架,它提供了动态SQL的功能。动态SQL是一种根据不同条件动态生成SQL语句的技术。 在Mabits中,动态SQL通常是通过使用一组特殊的标签和代码块来实现的,这些标签和代码块可以根据条件包含或排除不同的部分,从而生成不同的SQL语句。 动态SQL可以让开

    2024年02月06日
    浏览(38)
  • 【MyBatis】四、MyBatis中的动态SQL标签

    动态SQL语句是动态的拼接Mybatis中SQL语句的情况,可以动态的在Mybatis中使用SQL if语句的xml文件: 传入对象来进行调用: where标签中的and会被自动去掉,并且若没有合适的内容,则不会添加where 注意:where标签只能去掉条件前的and、五福去掉条件后的and trim标签会在其内容

    2024年02月09日
    浏览(39)
  • 使用MyBatis的mapper接口调用时有哪些要求?Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql?

    1. Mapper接口方法名和mapper.xml中定义的每个 sql的id相同 2.Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的 parameterType的类型相同 3.Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的 resultType的类型相同 4.Mapper.xml文件中的 namespace 即是 mapper接口的类路径 可以在

    2024年02月16日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包