0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MyBatis动态sql是什么?MyBatis动态SQL最全教程

jf_ro2CN3Fa 来源:CSDN 2023-08-10 10:18 次阅读

一、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 标 签有哪些?

元素 作用 备注
if 判断语句 单条件分支判断
choose(when、otherwise) 相当于 Java 中的 switch case 语句 多条件分支判断
trim,where 辅助元素 用于处理一些SQL拼装问题
foreach 循环语句 在in语句等列举条件常用
bind 辅助元素 拼接参数

3.动态 sql 的执行原理?

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

二、MyBatis标签

1.if标签:条件判断

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

1)不使用动态sql


 
select*fromuserwhereusername=#{username}andsex=#{sex}

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

SQL语句

2)使用动态sql

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

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


selectid,name,urlfromwebsite
where1=1

ANDnamelike#{name}


ANDurllike#{url}


2.where+if标签

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

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





sacclikeconcat('%'#{sacc}'%')


ANDsnamelikeconcat('%'#{sname}'%')


ANDsex=#{sex}


ANDphone=#{phone}



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

3.set标签

set可以用来修改


updatestudent

sname=#{sname},
spwd=#{spwd},
sex=#{sex},
phone=#{phone}
sid=#{sid}

wheresid=#{sid}

4.choose(when,otherwise) 语句

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


select*fromuser



id=#{id}


andusername=#{username}


andsex=#{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*fromuser
 


andusername=#{username}


andsex=#{sex}



prefix:前缀

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

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

 

updateuseru
 


u.username=#{username},


u.sex=#{sex},



whereid=#{id}

suffix:后缀

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

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


insertintostudent

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 是值。

//批量查询

WHEREsidin

#{ids}


//批量删除

deletefromstudentwheresidin

#{ids}


整合案例

xml





select*fromstudent








WHERE1=1

ANDsidlike#{sid}







sacclikeconcat('%'#{sacc}'%')


ANDsnamelikeconcat('%'#{sname}'%')


ANDsex=#{sex}


ANDphone=#{phone}





updatestudent

sname=#{sname},
spwd=#{spwd},
sex=#{sex},
phone=#{phone}
sid=#{sid}

wheresid=#{sid}



insertintostudent

sname,
spwd,
sex,
phone,



#{sname},
#{spwd},
#{sex},
#{phone}




WHEREsidin

#{ids}




deletefromstudentwheresidin

#{ids}






测试类:

packagecom.yzx.test;

importcom.yzx.entity.Student;
importcom.yzx.mapper.StuMapper;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importorg.junit.After;
importorg.junit.Before;
importorg.junit.Test;

importjava.io.IOException;
importjava.io.InputStream;
importjava.util.List;

publicclassStuTest{
SqlSessionsqlSession=null;
InputStreamis=null;

@Before
publicvoidbefore()throwsIOException{
//1.读取核心配置文件
is=Resources.getResourceAsStream("sqlMapperConfig.xml");
//2.拿到工厂构建类
SqlSessionFactoryBuildersqlSessionFactoryBuilder=newSqlSessionFactoryBuilder();
//3.拿到具体工厂
SqlSessionFactorybuild=sqlSessionFactoryBuilder.build(is);
//4.拿到session
sqlSession=build.openSession();
}

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

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

StuMappermapper=sqlSession.getMapper(StuMapper.class);
Listlist=mapper.findbyid(2);
list.forEach(a->System.out.println(a));
}
//模糊查询
@Test
publicvoidfindQuery(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);

Studentstu=newStudent();
stu.setSname("小");
stu.setSex("男");
Listlist=mapper.findQuery(stu);
list.forEach(a->System.out.println(a));
}
//修改
@Test
publicvoidupd(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);

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

}
//添加
@Test
publicvoidadd(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);

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

}

//批量操作
@Test
publicvoidfindAll(){

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

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

7.sql

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

当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求

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*fromstudent1sleftjointeachertons.sid=t.sid

2.MyBatis多对一关联查询

 













 

select*fromteachertrightjoinstudent1sont.sid=s.sid

3.MyBatis多对多关联查询

 

select*fromstudent1sleftjoinrelevancerons.sid=r.sidleftjointeachertonr.tid=t.tid





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SQL
    SQL
    +关注

    关注

    1

    文章

    738

    浏览量

    43463
  • JAVA语言
    +关注

    关注

    0

    文章

    138

    浏览量

    19944
  • XML技术
    +关注

    关注

    0

    文章

    15

    浏览量

    5990
  • UTF-8
    +关注

    关注

    0

    文章

    13

    浏览量

    7817
  • mybatis
    +关注

    关注

    0

    文章

    57

    浏览量

    6646

原文标题:MyBatis 动态 SQL 最全教程,这样写 SQL 太爽了!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Mybatis的特点和核心配置文件

    Mybatis—01基础&动态SQL
    发表于 08-07 14:20

    为什么要动态sql语句?

    为什么要动态sql语句?因为动态sql语句能够提供一些比较友好的机制1、可以使得一些在编译过程中无法获得完整的sql语句,在程序执行阶段
    发表于 12-20 06:00

    jdbc与mybatis的区别

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。JDBC是一种用于执行SQL
    发表于 02-02 17:43 1.1w次阅读
    jdbc与<b class='flag-5'>mybatis</b>的区别

    mybatis是什么_MyBatis的优缺点详解_mybatis框架入门详解

    Mybatis框架是别人开发的一种半成品软件,可以用来通过定制辅助快速开发是工具。MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory
    发表于 02-24 09:16 1.9w次阅读

    mybatis动态sql详解

    本文详细介绍了mybatis执行动态sql语句的方法。
    发表于 02-24 11:37 3688次阅读

    mybatis中#和$的区别

    ${ } 变量的替换阶段是在动态 SQL 解析阶段,而 #{ }变量的替换是在 DBMS 中。这是 #{} 和 ${} 我们能看到的主要的区别,除此之外,还有以下区别:#方式能够很大程度防止sql
    发表于 02-24 13:35 2054次阅读

    在使用MyBatisSQL语句优化总结

    MyBatis 作为一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。它免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。还可以通过简单的 XML 或注解来配置和映射原始
    的头像 发表于 02-04 15:20 2496次阅读

    MybatisSQL注入审计的基本方法

    SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少。新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知如何下手,希望通过Mybatis框架使用不当导致的S
    的头像 发表于 10-17 11:16 991次阅读

    怎样去解决MyBatis引起的线程池线程打满问题呢

    于是我们根据提示找到相应的源码处进行分析。mybatis 组装 sql 语句这里,这段代码,在 sql 很长的并且入参很多说的时候,下面对 sql 的拼接,将#{属性名}替换成?是很耗
    的头像 发表于 10-17 16:24 1296次阅读

    一文掌握MyBatis动态SQL使用与原理

    摘要:使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,M
    的头像 发表于 01-06 11:27 662次阅读

    高逼格的SQL写法:行行比较

    同样是利用 Mybatis动态 SQL ,将 business_id 列表拼在一起、 ware_inside_code 拼在一起,类似如下
    的头像 发表于 05-12 10:51 387次阅读
    高逼格的<b class='flag-5'>SQL</b>写法:行行比较

    动态Sql介绍

    动态Sql介绍 动态 SQLMyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接
    的头像 发表于 05-31 09:34 1099次阅读
    <b class='flag-5'>动态</b><b class='flag-5'>Sql</b>介绍

    mybatis接口动态代理原理

    MyBatis是一款轻量级的Java持久化框架,它通过XML或注解配置的方式,将数据库操作与SQL语句解耦,提供了一种简单、灵活的数据访问方式。在MyBatis中,使用动态代理技术来实
    的头像 发表于 12-03 11:52 436次阅读

    mybatis和mybatisplus的区别

    是一个轻量级的持久层框架,它提供了一个灵活的SQL映射机制,使得开发者可以编写原生SQL语句来操作数据库。MyBatis的设计目标是将原生SQL和对象关系映射(ORM)相结合,以便开发
    的头像 发表于 12-03 11:53 1328次阅读

    mybatis中$和井号区别

    MyBatis是一个开源的Java持久层框架,它提供了许多强大的功能用于简化数据库操作。在MyBatis中,我们可以使用两种方式来动态生成SQL语句:$和#。 和#都可以用来替换
    的头像 发表于 12-03 14:53 521次阅读