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

您所在的位置:网站首页 悍妻穿越小说 MyBatis动态SQL最全教程,这样写SQL太爽了!

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

2024-07-14 16:51:23| 来源: 网络整理| 查看: 265

一: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 标 签有哪些? d3b64efe8e3bc6ba9bf1c7be25a7daf0.jpeg 3.动态 sql 的执行原理?

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

二:MyBatis标签 1.if标签:条件判断

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

1)不使用动态sql

         select * from user where username=#{username} and sex=#{sex}

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

    SQL语句

2)使用动态sql

上面的查询语句,我们可以发现,如果 #{username} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断,可多个 if 语句同时使用。划水摸鱼:https://www.yoodb.com/slack-off/home.html

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

       select id,name,url from website      where 1=1                        AND name like #{name}                               AND url like #{url}         2.where+if标签

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

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

                               sacc like concat('%' #{sacc} '%')                               AND sname like concat('%' #{sname} '%')                               AND sex=#{sex}                               AND phone=#{phone}              

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

3.set标签

set可以用来修改

    update student              sname=#{sname},         spwd=#{spwd},         sex=#{sex},         phone=#{phone}     sid=#{sid}          where sid=#{sid} 4.choose(when,otherwise) 语句

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

      select * from user                                                    id=#{id}                                                 and username=#{username}                                                 and sex=#{sex}                                    

也就是说,这里我们有三个条件,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标记的功能

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

    select * from user                               and username=#{username}                              and sex=#{sex}              

prefix:前缀

prefixoverride:去掉第一个and或者是or

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

    update user u                                                u.username = #{username},                                           u.sex = #{sex},                                  where id=#{id}

suffix:后缀

suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

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

    insert  into student              sname,         spwd,         sex,         phone,                   #{sname},         #{spwd},         #{sex},         #{phone}      6.MyBatis foreach标签

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

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

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

//批量查询      WHERE sid in              #{ids}      //批量删除     delete  from  student  where  sid in              #{ids}      整合案例

xml

             select  *  from  student                                                    WHERE 1=1                      AND sid like #{sid}                                                                                       sacc like concat('%' #{sacc} '%')                                                       AND sname like concat('%' #{sname} '%')                                                       AND sex=#{sex}                                                       AND phone=#{phone}                                                     update student                      sname=#{sname},             spwd=#{spwd},             sex=#{sex},             phone=#{phone}         sid=#{sid}                  where sid=#{sid}                   insert  into student                      sname,             spwd,             sex,             phone,                               #{sname},             #{spwd},             #{sex},             #{phone}                             WHERE sid in                      #{ids}                            delete  from  student  where  sid in                      #{ids}              

测试类:

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 list=mapper.find();         list.forEach(a-> System.out.println(a));     }     //查询单个     @Test     public  void  findbyid(){         StuMapper mapper=sqlSession.getMapper(StuMapper.class);         List 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 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 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  *  from  student 8.include

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

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

         WHERE 1=1              AND sid like #{sid}      9.如何引用其他XML中的SQL片段

比如你在com.xxx.dao.xxMapper这个Mapper的XML中定义了一个SQL片段如下:

 ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY

此时我在com.xxx.dao.PatinetMapper中的XML文件中需要引用,如下:

三:MyBatis关联查询 1.MyBatis一对多关联查询                                                              select  *  from  student1  s  left  join  teacher  t  on s.sid=t.sid 2.MyBatis多对一关联查询                                                              select  *  from  teacher  t right join student1 s on  t.sid=s.sid 3.MyBatis多对多关联查询     select  *  from  student1 s  left join relevance r on  s.sid=r.sid  left join teacher t on  r.tid=t.tid

作者:变成秃头怪

https://blog.csdn.net/SGLP521/article/details/121509714

公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理! 最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群! Java精选面试题(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题! ------ 特别推荐 ------ 特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注。 点击“阅读原文”,了解更多精彩内容!文章有帮助的话,点在看,转发吧!


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭