当前位置: 首页 > news >正文

学会Mybatis框架:让你的代码更具灵活性、可维护性、安全性和高效性【二.动态SQL】

🥳🥳Welcome Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于Mybatis的相关操作吧

        

目录

🥳🥳Welcome Huihui's Code World ! !🥳🥳

一.Mybatis动态SQL如何应用

1.需求

2.问题分析

3.为什么使用动态SQL

二.Mybatis中的常用标签

1.if标签

2.foreach标签

三. 使用Mybatis中的动态SQL完成模糊查询

1.使用#{字段名}

2.使用${字段名}

3.使用concat{'%',#{字段名},'%'}

四、MyBatis结果映射 

1.resultType进行结果映射

2.resultMap进行结果映射


在学习一个东西之前,我们应该要知道它能够给我带来哪些好处,这样的话,我们学习它才会更有目标性,更有方向感。那我们采用对比的方式,来看看Mybatis到底解决了我们什么问题

        当我们还是初级开发工程师的时候,可能写过这样的代码:

//我们需要修改商品的信息,那我们就需要拿到它的id,然后再去修改它的相关信息
String sql="update goods set bname =?, price=? where bid =?"
//如果我此时没有传递bname,因为在我的业务功能中我不需要修改bname,
//那么我在传参的时候我就不会给它传递值,我预想的结果应该是它会照样是之前的那个值,
//可是它却变成了null!!!
String sql="update goods set bname =null, price=1232 where bid =2"
//这是因为我们没有传值,所以会默认给一个null值

        还有当我们写了电商项目中的购物车,那我们应该就会遇到这样的情况:当我们需要全选进行结算时。那么我们需要拿到用户所选商品的id,如果用户选择了多个,那么我们就要将这几个用户选中的id接收(数组),然后遍历,再将其分割,再执行sql语句...

        类似上述这样的情况,还有很多,它们都指向了一个问题:就是我们的sql语句没法很好的被改动,一动则要修改很多地方,所以很多初级开发员通常不会选择动sql,而是选择去适应sql语句,多写一些代码,但这样往往是行不通的...

        所以,我们今天要了解的是一个秘密神器--Mybatis中的动态sql!!!

一.Mybatis动态SQL如何应用

1.需求

假设我们要查询用户信息,但是用户的年龄可能在不同的范围内,我们需要根据年龄的不同来查询不同的信息。

2.问题分析

这个问题需要我们在运行时根据年龄的不同来生成不同的SQL语句,这就需要使用到动态SQL

3.为什么使用动态SQL

因为动态SQL可以根据不同的条件生成不同的SQL语句,这样就可以满足我们的需求

应用过程和解答步骤:首先,我们需要在Mapper接口中定义一个方法,该方法接收一个年龄参数;然后,在对应的XML文件中编写动态SQL;最后,在Service层调用这个方法。

【如果年龄小于18岁,那么就查询用户的名字和年龄;如果年龄大于等于18岁且小于60岁,那么就查询用户的姓名、年龄和性别;如果年龄大于等于60岁,那么就查询用户的姓名、年龄和电话】

上面的文字分析,你或许还是会觉得很懵,那么接下来我就用代码来演示意识使用动态SQL的好处, 那么我将会讲到mybatis动态SQL中比较常用的两种的标签

二.Mybatis中的常用标签

1.if标签

假设我们需要查询某个书城的所有神话小说,包括书名中含有为"圣墟"的和书本ID为56的。 首先需要根据书名中含有为"圣墟"的查询到对应的信息,然后根据书本ID和书名查询到对应的书本信息

这里需要使用if标签来实现动态拼接SQL

 d. 应用过程和解答步骤:首先使用if标签判断书本ID是否存在,如果存在则拼接查询书本信息的SQL语句,书名也是一样,如果都存在,则将这两个SQL语句拼接起来,得到最终的查询结果

<select id="selectBook" parameterType="Book" resultType="Book">SELECT * FROM Book WHERE 1=1<if test="bname!= null">AND bname like #{bname}</if><if test="bid!= null ">AND bid like #{bid}</if>
</select>

2.foreach标签

 <select id="selectByBid" resultType="com.wh.model.Book" parameterType="java.util.List" >select<include refid="Base_Column_List" />from t_mvc_bookwhere bid in<foreach collection="bids" item="bid" open="(" close=")" separator=",">#{bid}</foreach></select>

然后需要在BookMapper中写方法

 List<Book> selectByBid(@Param("bids") List bids);

BookBiz

  List<Book> selectByBid(List bids);

BookBizImpl

  @Overridepublic List<Book> selectByBid(List bids) {return bookMapper.selectByBid(bids);}

测试

  @Testpublic void selectByBid() {List<Integer> bids = Arrays.asList(new Integer[]{56,57,58});bookBiz.selectByBid(bids).forEach(System.out::println);}

结果

三. 使用Mybatis中的动态SQL完成模糊查询

1.使用#{字段名}

 <select id="selectBooksLike1" resultType="com.wh.model.Book" parameterType="java.lang.String">select * from t_mvc_book where bname like #{bname}
</select>

写完这个xml文件的代码之后,也需要像上面的foreach标签那样在BookBiz,BookBizImpl...中写相应的代码,因为代码逻辑都相似,在这里我就不做过多的赘述了...

结果

2.使用${字段名}

  <select id="selectBooksLike2" resultType="com.wh.model.Book" parameterType="java.lang.String">select * from t_mvc_book where bname like ${bname}
</select>

 我们使用${字段名}的时候,需要格外注意,因为容易出现问题

 那么这是为什么呢?我们可以看下面这张图

我们也可以对比看看使用#{字段名}时,参数是什么样的

那我们应该怎么解决呢?其实很简单,看下面的代码👇

  <select id="selectBooksLike2" resultType="com.wh.model.Book" parameterType="java.lang.String">select * from t_mvc_book where bname like '${bname}'
</select>

 那么就阔以看到结果了

3.使用concat{'%',#{字段名},'%'}

<select id="selectBooksLike3" resultType="com.wh.model.Book" parameterType="java.lang.String">select * from t_mvc_book where bname like concat('%',#{bname},'%')
</select>

 结果

  •  #{字段名}和${字段名}的区别
    • #{}表示使用用户输入的值作为参数,而${}表示使用预定义的变量值作为参数
    • #自带引号$传参不带引号
    • ${}
    • ${}可能会导致SQL注入的风险,因为它允许我们在SQL语句中插入任意的值(SQL注入攻击:SQL注入是一种代码注入技术,攻击者通过在SQL语句中插入恶意的代码来控制数据库。为了防止SQL注入,我们应该尽量避免直接拼接SQL语句,而应该使用参数化查询或者其他安全的方法)
      • 举个例子说明一下:

        假设有一个Web应用,用户可以通过搜索框输入关键词查询商品信息。现在我们要分析这个应用是否存在SQL注入的风险。

        在这个应用中,用户输入的关键词会被拼接到SQL查询语句中,如:SELECT * FROM products WHERE keyword = '用户输入的关键词';。如果攻击者在搜索框中输入特殊字符,如单引号('),那么拼接后的查询语句可能变成:SELECT * FROM products WHERE keyword = '' OR '1'='1';。这样,原本的查询条件就被绕过了,攻击者可以获取到所有商品的详细信息

    • ${}也有它的好处,它可以用来做动态列
      • 举个例子说明一下:

        假设我们有一个销售记录表,其中包含以下列:产品ID、产品名称、销售数量、销售日期和销售价格。现在,我们希望根据销售数量对产品进行分组,并计算每个产品的总销售额。

        为了实现这个需求,我们需要在表中添加一个新列(例如“产品类别”),并根据销售数量对数据进行分组。然后,我们可以使用聚合函数(如SUM)来计算每个产品的总销售额,但是这样的话,我们需要修改的地方就有很多,那么这个时候我们就可以用到动态列,因为动态列允许我们在不修改表结构的情况下实现这个需求

四、MyBatis结果映射 

在使用MyBatis中拥有多个场景,返回的结果是多样的,resultType/resultMap

1返回单表的对应的实体类,仅有一个查询结果,可以用resultType/resultMap

2返回单表的对应的实体类,有多个查询结果,可以用resultType/resultMap

3返回多表对应结果,仅有一个查询结果,通常用resultType也可以用resultMap

4返回多表对应结果,有多个查询结果,通常用resultType也可以用resultMap

5返回单个列段,仅有一个查询结果,就用resultType

6返回单个列段,有多个查询结果,就用resultType

  总结就是在Mybatis中结果集的处理分为两种:

①resultMap:适合使用返回值是自定义实体类的情况

②resultType:适合使用返回值的数据类型是非自定义的,即jdk的提供的类型

 如果是单表的情况下,resultType与resultMap都可以使用。
1 使用resultMap返回映射关系,指的是实体类与数据库字段的关系

2 使用resultType返回List<T>

3 使用resultType返回单个对象

4 使用resultType返回List<Map>【适用于多表查询返回结果集】

5 使用resultType返回Map<String,Object>【适用于多表查询返回单个结果集】
 

1.resultType进行结果映射

假设我们有一个用户表user,包含以下字段:id、name、age、gender、email。现在需要根据这些字段查询用户信息并返回一个User对象。

首先,我们需要定义一个User类,用于存储查询结果:

public class User {private int id;private String name;private int age;private String gender;private String email;// getter和setter方法省略
}

然后,在MyBatis的mapper文件中,我们可以使用resultType来映射查询结果到User对象上

<select id="getUserById" resultType="com.example.User">SELECT id, name, age, gender, emailFROM userWHERE id = #{id}
</select>

在上面的配置中,我们使用了resultType属性来指定查询结果映射到的Java对象的全限定名。这样,当执行查询语句时,MyBatis会自动将查询结果映射到指定的Java对象上

2.resultMap进行结果映射


假设我们有一个订单表order,包含以下字段:id、user_id、product_id、price、quantity。现在需要根据这些字段查询订单信息并返回一个Order对象

首先,我们需要定义一个Order类,用于存储查询结果:

public class Order {private int id;private int userId;private int productId;private double price;private int quantity;// getter和setter方法省略
}

然后,在MyBatis的mapper文件中,我们可以使用resultMap来映射查询结果到Order对象上。具体配置如下:


<resultMap id="OrderResultMap" type="com.example.Order"><id property="id" column="id" /><result property="userId" column="user_id" /><result property="productId" column="product_id" /><result property="price" column="price" /><result property="quantity" column="quantity" />
</resultMap>
<select id="getOrderById" resultMap="OrderResultMap">SELECT id, user_id, product_id, price, quantityFROM orderWHERE id = #{id}
</select>

在上面的配置中,我们定义了一个名为"OrderResultMap"的resultMap,它的type属性指定了要映射的Java对象的全限定名。接下来,我们为每个字段指定了对应的属性名和数据库表中的列名。最后,在查询语句中引用这个resultMap即可将查询结果映射到Order对象上。

需要注意的是,如果查询结果中的某个字段在Java对象中没有对应的属性,那么该字段将被映射为null。此外,如果查询结果中的某个字段在Java对象中有多个对应的属性,那么该字段的值将被映射为一个列表或数组

 好啦,今天的分享就到这了,希望能够帮到你呢!😊😊     

相关文章:

学会Mybatis框架:让你的代码更具灵活性、可维护性、安全性和高效性【二.动态SQL】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Mybatis的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Mybatis动态SQL如何应用 1.需求 2.…...

Oracle 中 ROWNUM 使用问题记录

ROWNUM 使用问题记录(2023-08-17) Oracle 版本&#xff1a; 19.0.0.0.0 Enterprise现象&#xff1a;今天在项目遇到一个问题&#xff0c;测试人员反馈前一天能看到的数据今天看不到了 用表格举例&#xff0c;这是前一天看到的数据&#xff0c;有9、7、1 这几个数量信息 日期…...

MySQL数据库:内置函数

日期函数 规定&#xff1a;日期&#xff1a;年月日 时间&#xff1a;时分秒 函数名称作用描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date_add(date,interval d_value_type)在date中添加…...

【C++杂货铺】探索string的底层实现

文章目录 一、成员变量二、成员函数2.1 默认构造函数2.2 拷贝构造函数2.3 operator2.4 c_str()2.5 size()2.6 operator[ ]2.7 iterator2.8 reserve2.9 resize2.10 push_back2.11 append2.12 operator2.13 insert2.14 erase2.15 find2.16 substr2.17 operator<<2.18 opera…...

c++ day1

定义一个命名空间Myspace&#xff0c;包含以下函数&#xff1a;将一个字符串中的所有单词进行反转&#xff0c;并输出反转后的结果。例如&#xff0c;输入字符串为"Hello World"&#xff0c;输出结果为"olleH dlroW"&#xff0c;并在主函数内测试该函数。 …...

变动的Python爬虫实现

在电商时代&#xff0c;了解商品价格的变动对于购物者和卖家来说都非常重要。本文将分享一种基于Python的实时监控电商平台商品价格变动的爬虫实现方法。通过本文的解决方案和代码示例&#xff0c;您将能够轻松监控商品价格&#xff0c;并及时做出决策。 一、了解需求和目标 在…...

mybatis-plus--配置-(sql)日志输出-自动填充-分页-多数据源-逻辑删除

写在前面&#xff1a; 本文主要介绍mybatis-plus的配置&#xff0c;以后在有的时候在补充。欢迎交流。 文章目录 日志输出自动填充分页全局字段配置多数据源 日志输出 调试的时候需要看执行的sql&#xff0c;这时候就很需要日志来记录查看了。 mybatis-plus的日志配置在yml…...

数据API服务管理功能:解放数据潜力,提升业务效率

数据API服务的重要性 在数字化时代&#xff0c;数据被认为是企业的重要资产。数据API服务的管理功能能够有效帮助企业实现数据的整合和利用。通过合理的数据API服务管理&#xff0c;企业可以更好地解放数据潜力&#xff0c;提升业务效率。 ​ 解放数据潜力 数据API服务管理功…...

云南森林火灾vr消防模拟安全演练系统训练消防员火灾和事故的适应和应对能力

据统计,每一场破坏性地震发生后,会引发次生的灾害,而火灾是其中之一。导致火灾的原因,推测是地震时使供电线路短路,引燃易燃物,火灾就随即发生。所以,在日常生活中,定期的消防演练还是非常必要的, VR消防&#xff0c;是VR公司深圳华锐视点利用VR虚拟现实技术&#xff0c;将VR和…...

(6)(6.2) 任务命令

文章目录 前言 6.2.1 概述 6.2.2 导航命令 6.2.3 条件命令 6.2.4 DO命令 前言 本文介绍了 Copter、Plane 和 Rover 切换到自动模式时支持的任务指令。 &#xff01;Warning 这是一项正在进行中的工作&#xff0c;尚未经过全面审核。有关 Copter 的更佳列表&#xff0c;请…...

【consul】

consul 一、什么是服务注册与发现1.11.2 二、 什么是consul2.1定义2.2特性2.2.1服务注册与发现&#xff1a;2.2.2健康检查&#xff1a;2.2.3Key/Value存储&#xff1a; 三、consul部署-datacenter &#xff1a;指定数据中心名称&#xff0c;默认是dc1。consul &#xff1a;指定…...

Electron环境搭建

Electron是一个优秀的开源框架&#xff0c;用于构建跨平台的桌面应用程序。它基于Chromium和Node.js&#xff0c;使得开发者可以使用Web技术&#xff08;HTML、CSS和JavaScript&#xff09;来构建可在Windows、macOS和Linux等多个操作系统上运行的应用程序。本文将介绍如何搭建…...

MinIO线上扩容实战

硬件投入肯定是随着业务的增长而增长&#xff0c;这就要求中间件平台必须提供水平伸缩机制&#xff0c;MinIO对象存储服务也不例外&#xff0c;本文就详细介绍MinIO的扩容。 Minio支持通过增加新的Server Pool来扩容老的集群。每个Server Pool都是一个相对独立的故障域&#x…...

【微服务】微服务的概论

微服务&#xff1a;构建面向为了解决这个问题&#xff0c;微服务架构应运而生。本文将向您介绍微服务的概念、优势、实现原理以及应用场景&#xff0c;带您领略微服务在构建面向未来的高效应用中的魅力。 一、微服务的概念和优势 微服务是一种将应用拆分为一系列小型、独立服…...

基于Jenkins自动打包并部署docker环境

目录 1、安装docker-ce 2、阿里云镜像加速器 3、构建tomcat 基础镜像 4、构建一个Maven项目 实验环境 操作系统 IP地址 主机名 角色 CentOS7.5 192.168.200.111 git git服务器 CentOS7.5 192.168.200.112 Jenkins git客户端 jenkins服务器 CentOS7.5 192.168…...

jvm 运行时数据区

Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁 1.1程序计数器 程序计数器也叫pc寄存器 可以看作是当前线程…...

Jobs Portal求职招聘系统源码v3.5版本

Jobs Portal求职招聘系统 是为求职者和公司发布职位而开发的交互式求职招聘源码。它使求职者能够发布简历、搜索工作、查看个人工作列表。 它将提供各种公司在网站上放置他们的职位空缺资料&#xff0c;并且还可以选择搜索候选人简历。 除此之外&#xff0c;还有一个管理模块供…...

Android kotlin系列讲解(入门篇)使用Intent在Activity之间穿梭

<<返回总目录 上一篇:Android kotlin系列讲解(入门篇)Activity的理解与基本用法 文章目录 1、使用显式Intent2、使用隐式Intent3、更多隐式Intent的用法4、向下一个Activity传递数据5、返回数据给上一个Activity1、使用显式Intent 你应该已经对创建Activity的流程比较…...

音频编码类型及对应的封装文件

音频编码类型及对应的封装文件 如下表格 编码类型解释文件封装audio/mp4a-latmMPEG-4 Audio Advanced Audio Coding (AAC) Low-Overhead Audio Transport Multiplex (LATM) 压缩的音频格式mp4audio/3gpp3rd Generation Partnership Project (3GPP) 定义的音频编码格式3GPaudi…...

初探科研 | 第一次科研经历

1 . 自己的experiences 自己大二下学期中比较幸运加入到科研组里&#xff0c;做的方向是3D人体姿态估计&#xff0c;不过由于是一个全新领域&#xff0c;基本也是自己这个小白探索&#xff0c;所以成果甚微。在八月初由于各种原因退出了组&#xff0c;但是在这期间收获还是蛮多…...

Wireshark数据抓包分析之HTTP协议

一、实验目的&#xff1a; 主要时熟悉wireshark的使用 二、预备知识&#xff1a; HTTP协议的相关知识 what fk&#xff0c;原来只要在右页点击切换&#xff0c;就可以开启2台不同的机器欸&#xff01;nice 三、实验过程&#xff1a; 1.在机器1中通过管理员身份运行hfs之后&a…...

研发管理工具大揭秘!6款利器助你高效研发

"研发管理工具有哪些&#xff1f;6款研发管理利器分析Zoho Projects、Trello、Asana、Monday.com、Smartsheet、Jira。" 在如今的科技发展日新月异的时代&#xff0c;研发管理工具的重要性日益凸显。研发管理工具有助于提高研发效率&#xff0c;降低成本&#xff0c;…...

云知识入门-什么是虚拟机、磁盘、镜像和快照

一、虚拟机 1、什么是虚拟机 虚拟机&#xff08;VM&#xff09;是一种创建于物理硬件系统&#xff08;位于外部或内部&#xff09;、充当虚拟计算机系统的虚拟环境&#xff0c;它模拟出了自己的整套硬件&#xff0c;包括 CPU、内存、网络接口和存储器。通过名为虚拟机监控程序…...

C/C++编译整理

1. 编译器 查看编译情况 gcc main.c -o main -v # -v查看编译详情 g main.c -o main -v # -v查看编译详情添加预处理头文件 在PATH中找到可执行文件程序的路径 export PATH $PATH:$HOME/bin gcc找到头文件的路径 C_INCLUDE_PATH/usr/include/libxml2:/MyLib export C_I…...

数据结构——栈和队列

栈和队列的建立 前言一、栈1.栈的概念2.栈的实现3.代码示例&#xff08;1&#xff09;Stack.h&#xff08;2&#xff09;Stack.c&#xff08;3&#xff09;Test.c&#xff08;4&#xff09;运行结果&#xff08;5&#xff09;完整代码演示 二、队列1.队列的概念2.队列的实现3.代…...

苍穹外卖阿里云oss存储笔记

阿里云oss 阿里云对象存储oss&#xff08;Object Storage Service&#xff09;&#xff0c;是一款海量&#xff0c;安全&#xff0c;低成本&#xff0c;高可靠得云存储服务&#xff0c;使用oss&#xff0c;您可以通过网络随时存储和调用包括文本&#xff0c;图片&#xff0c;视…...

Kafka 集群搭建过程

前言 跟着尚硅谷海哥文档搭建的Kafka集群环境&#xff0c;在此记录一下&#xff0c;侵删 注意&#xff1a;博主在服务器上搭建环境的时候使用的是一个服务器&#xff0c;所以这篇博客可能会出现一些xsync分发到其他服务器时候的错误&#xff0c;如果你在搭建的过程中出现了错…...

【算法随记】在计算过程中模的情况

https://leetcode.cn/problems/power-of-heroes/ 计算过程中&#xff0c;可以放心模的情况&#xff1a; 加减乘 先模再加再模和直接加再模一样 a m o d m b m o d m ≡ a b ( m o d m ) a\mod mb\mod m ≡ ab \ (\mod m) amodmbmodm≡ab (modm) 先模再减再模和直接减再模…...

MSTP多生成树协议(第二课)

MSTP负载均衡 实验 需求 1&#xff09;PC1属于 vlan 10 &#xff0c;IP地址为 192.168.10.1/24&#xff0c; 网关为 192.168.10.2542&#xff09;PC2属于 vlan 20 &#xff0c;IP地址为 192.168.20.1/24&#xff0c; 网关为 192.168.20.254**3&#xff09;确保PC1与PC2互通4…...

数组指针、函数指针、指针数组、函数 指针数组、指针函数详细总结

1.数组指针概念和应用 首先数组指针应该是一个数组&#xff0c;它的定义如下&#xff1a; 数组指针&#xff0c;指的是数组名的指针&#xff0c;即数组首元素地址的指针。即是指向数组的指针。例&#xff1a;int (*p)[10]; p即为指向数组的指针&#xff0c;又称数组指针。 数…...

网站收录原创文章/上海关键词推广公司

jQuery自己定义绑定 首先让我们来看看jQuery的自己定义绑定的用法&#xff0c;你能够使用bind或者live来订阅一个事件&#xff08;当然1.7以后也能够使用on了&#xff09;&#xff0c;代码例如以下&#xff1a; $("#myElement").bind(customEventName,function(e){ .…...

wordpress query_posts 分页/宁波网站推广排名

Linux中找不到ifconfig命令的解决方法参考文章&#xff1a; &#xff08;1&#xff09;Linux中找不到ifconfig命令的解决方法 &#xff08;2&#xff09;https://www.cnblogs.com/dxqNet/p/11479395.html 备忘一下。...

中国菲律宾男篮直播/东莞seo外包公司

Linux内核模块编程入门看到昨天有好几个问linux内核编程问题的帖子&#xff0c;不少是卡在了入门问题上&#xff0c;就整理一下入门的初步流程。针对2.6内核的Linux系统&#xff0c;需要你的机器上已经安装了kernel-devel这个包&#xff0c;也就是编译模块所必须的东西&#xf…...

手机中国建设银行网站/整合营销传播方案案例

由于在Web端&#xff0c;JavaScript不能直接处理本地文件&#xff0c;因此可以在后台裁剪图片&#xff0c;或者利用html5的canvas来处理。 方法1&#xff1a;传送到后台剪切 步骤1&#xff1a;上传图片到后台&#xff0c;向前端返回图片URL 利用input标签&#xff0c;将文件发送…...

wordpress 动态主题下载/百度推广开户多少钱一个月

算法&#xff1a; 题目&#xff1a; 计算&#xff1a; end...

微信小程序开发实例教程/seo公司网站推广

In the given example, we are printing the messages by using different forms of the print() method in Python. 在给定的示例中&#xff0c;我们通过使用Python中不同形式的print()方法来打印消息。 Consider the program: 考虑该程序&#xff1a; # it will print new …...