【MyBatis】Spring Boot整合MyBatis操作数据库

news2024/11/25 10:32:54

文章目录

  • 1. MyBatis是什么?
  • 2. 为什么要学MaBatis?
  • 3. MyBatis环境搭建
  • 4. MyBatis的使用
    • 4.1 简单示例
    • 4.2 获取动态参数
      • 4.2.1 ${xxx}获取动态参数
      • 4.2.2 #{xxx}获取动态参数
      • 4.2.3 #{xxx}与${xxx}获取字符串类型数据
      • 4.2.4 sql注入问题
      • 4.2.5 模糊查询like
      • 4.2.6 #{}与${}区别总结
  • 5. 修改操作(增删改)
  • 6. 查询操作
    • 6.1 resultType与resultMap
    • 6.2 单表查询
    • 6.3 多表查询
  • 7. 动态SQL
    • 7.1 \<if>标签
    • 7.2 \<trim>标签
    • 7.3 \<where>标签
    • 7.4 \<set>标签
    • 7.5 \<foreach>标签

1. MyBatis是什么?

MyBatis是一款持久层框架,它可更简单的完成程序与数据库之间交互的操作,它可以更简单的操作与读取数据库,它还支持自定义SQL,存储过程及高级映射

2. 为什么要学MaBatis?

对于后端开发来说,完整的程序由以下两部分组成:

  • 后端程序
  • 数据库

在这里插入图片描述

后端程序与数据库之间的通讯,就得依靠数据库连接工具,像之前学习的JDBC,但是因为JDBC使用起来太繁琐了,简单回顾使用JDBC操作数据库的步骤:

  1. 创建数据库连接池DataSource
  2. 使用DataSource获取数据库连接Connection
  3. 编写预编译的sql
  4. 使用Connection及sql创建操作命令对象Statement
  5. 替换占位符
  6. 使用Statement执行sql
  7. 如果是查询,则返回并处理结果集
  8. 释放资源

所以呢,使用MaBatis简化上述操作,方便快速的操作数据库

3. MyBatis环境搭建

创建Spring Boot项目的时候,添加MySQL驱动依赖与MyBatis框架依赖

在这里插入图片描述

创建好项目后,如果直接启动项目会报错,因为启动项目时候要连接数据库,此时我们还没有配置数据库源

在配置文件application.properties中配置数据库连接信息

# 配置数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/blog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=xiaobai520..@@@
# 配置数据库驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

在配置文件application.properties中配置MyBatis的xml文件路径

# 配置mybatis xml路径
# 在根路径下有mybatis文件夹,里面有xxxMapper.xml文件
mybatis.mapper-locations=classpath:/mybatis/*Mapper.xml

配置MyBatis中sql执行打印

#配置mybatis sql执行打印
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# sql打印日志的级别为debug,但是spring boot默认的打印级别为info
# 设置com.example.demo包下的打印级别为debug
logging.level.com.example.demo=debug

4. MyBatis的使用

4.1 简单示例

我们按照下面的流程来完成MyBatis操作数据库的功能

在这里插入图片描述

MyBatis模式开发由两部分组成:

  1. interface:让其他层可以注入使用的接口
  2. xxx.xml:具体的sql(可认为它是interface的实现)

具体步骤

创建Mapper接口
在这里插入图片描述
创建对应的xml文件
在这里插入图片描述
在xml中编写sql
在这里插入图片描述
创建service类调用接口中的方法

在这里插入图片描述
在controller类中调用service方法
在这里插入图片描述
启动项目,在浏览器输入访问地址,可以看到返回一条数据

在这里插入图片描述

4.2 获取动态参数

4.2.1 ${xxx}获取动态参数

上述的示例中,查询所有用户的信息,那此时如果想获得id为1的用户的信息该怎么操作?那就要在接口的方法中传递参数了

在这里插入图片描述
@Param与@RequestParam用法差不多,也是获取并赋值的意思,并且要求必传,也就是要必须能拿到@Param中的键对应的值

此时xml中的sql应该这样写:

在这里插入图片描述
使用${xxx}表示传递的参数,此时xxx必须与@Param中的键对应,如果接口方法中没有用@Param修饰形参,那xxx必须与形参名称对应

在测试类中运行结果如下:

在这里插入图片描述
在这里插入图片描述
发现使用${}获取动态参数会直接替换

4.2.2 #{xxx}获取动态参数

将sql改为使用#{xxx}的方式替换

在这里插入图片描述

再次执行测试类看打印结果:

在这里插入图片描述
在这里插入图片描述
发现使用#{}获取动态参数是采用占位符也就是预编译的方式替换

4.2.3 #{xxx}与${xxx}获取字符串类型数据

从上述的示例,获取数据库字段类型为int来看,使用这两种方式没有什么区别

此时使用名称获取用户数据,也就是数据库中字段类型为varchar,先使用#{}获取参数
在这里插入图片描述
启动测试,观察打印结果:发现正确获取到用户信息

在这里插入图片描述

将获取参数方式改为${},再观察打印结果:发现此时报错
在这里插入图片描述
原因:${}方式是直接替换,此时sql为select * from user where username=admin,但是正确的sql应该为select * from user where username=‘admin’,程序中执行的sql,admin没有带引号

如果使用KaTeX parse error: Double superscript at position 21: …数的话,我们可以手动加上`' '̲`,再观察打印情况 ![在这里…{}的话,会存在sql注入问题

4.2.4 sql注入问题

模拟登录,因为sql注入一般发生在登录阶段,使用${}获取参数
在这里插入图片描述

测试类,使用正确的用户名和密码:可正确获取用户数据

在这里插入图片描述

在这里插入图片描述

测试类,将用户密码改为错误的,观察打印结果:获取不到用户数据
在这里插入图片描述

测试类,使用错误的用户密码 ' or 1='1,观察打印结果:

在这里插入图片描述

发现尽管输入错误的密码,也是可以获取到用户数据,这就是典型的sql注入问题

我们再使用#{}方式获取参数,看看是否也可以获取到数据
在这里插入图片描述
发现使用错误的密码获取不到数据,也就是使用#{}不存在sql注入问题

4.2.5 模糊查询like

使用#{}进行模糊匹配
在这里插入图片描述

发现程序会报错,因为使用#{},sql变为select * from user where username like '%'a'%',因为#{}使用预编译的方式,对于字符串类型会加上一层引号,所以导致sql错误

此时可以使用concat拼接函数改造sql
在这里插入图片描述
在这里插入图片描述
发现如果对于like模糊查询,使用#{}的时候得结合concat()函数

除此外,我们可以使用${},因为${}是直接替换sql,所以不存在问题

在这里插入图片描述

在这里插入图片描述

4.2.6 #{}与${}区别总结

  • ${}是将参数直接替换到sql中,#{}是使用占位符也就是预编译的方式
  • 当参数为数值类型时,两种方式没区别
  • 当参数为字符串类型时,#{}使用占位符预执行,${}直接替换为sql,不加单引号,所以${}存在sql注入问题
  • 当参数为sql本身的时候,使用${}

5. 修改操作(增删改)

增加insert

在这里插入图片描述
打印结果:
在这里插入图片描述
观察数据库是否真正插入:发现插入数据库数据成功
在这里插入图片描述
我们在测试类中的方法默认是会持久化到数据库的,如果在方法加上 @Transactional,表示开启事务,则在方法执行结束会进行回滚操作,那么此次对数据库的操作将不会持久化

上述例子表示默认情况返回的是受影响的行数,但是我们增加一条数据时,想返回主键id,则可以按照如下方式进行操作
在这里插入图片描述
测试方法如下
在这里插入图片描述
打印结果:
在这里插入图片描述

  • useGeneratedKeys:开启还是关闭取出由数据库默认生成的主键,默认是false
  • keyProperty:唯一标识对象的属性,useGeneratedKeys获取的主键值赋值给keyProperty设置的属性
  • keyColumn:设置⽣成键值在表中的列名,如果⽣成列不⽌⼀个,可以⽤逗号分隔多个属性名称

删除delete

在这里插入图片描述

更新update

在这里插入图片描述

6. 查询操作

6.1 resultType与resultMap

resutType

我们上述的例子中查询操作都使用的是resultType,它是默认让数据库字段名与实体类属性名做了映射,也就是字段名与属性名必须对应起来,如果某个属性和字段没有对应,那么该字段的值就不会映射到属性上,导致该属性的值是一个null
在这里插入图片描述
如果字段与属性不对应的话,还想继续使用resultType的话,我们在可以使用as对字段起别名
在这里插入图片描述

resultMap

有时候程序中对象的属性和数据库的字段对应不起来,我们可以使用resultMap做映射

如下所示,user的属性pwd与数据库的password对应不起来,此时可以使用resultMap
在这里插入图片描述
在这里插入图片描述

6.2 单表查询

前面涉及到的查询都是单表查询,此处不过多介绍

6.3 多表查询

现在有两张表,user和article
在这里插入图片描述
我们现在如果要查询某篇文章,并且要查询出它的用户信息,也就是uid对应到user中id的用户的用户名(username)信息,此时发现我们的两个实体类User,Article都不能对应完成此次查询的所有信息
在这里插入图片描述

此时我们可以创建一个包vo,在此包下创建一个类ArticleVO,此类继承Article,并且添加一个属性username,此时该类就可完成我们此处的多表查询操作

在这里插入图片描述

@Data
public class ArticleVO extends Article {
    private String username;

    @Override 
    public String toString() {
        return "ArticleVO{" +
                "username='" + username + '\'' +
                '}'+super.toString();
    }
}

加了@Data注解为什么还要重写toString()?

因为@Data注解的toString方法只给该类的一个属性username输入打印,但是此类继承了Article,我们希望toString可以可以打印出继承的父类属性信息

创建ArticleMapper接口及ArticleMapper.xml文件

在这里插入图片描述
编写测试类及测试方法
在这里插入图片描述
启动观察结果:获取到我们想要的数据
在这里插入图片描述

7. 动态SQL

动态sql是MyBatis的强大特性之一,它可以完成不同条件下不同的sql拼接,它是在xml文件中进行不同条件拼接的

7.1 <if>标签

比如我们插入用户信息,有username(用户名),password(密码),photo(图像),但是当传递的用户信息中photo为null时,我们就不插入photo信息,如果用户信息中photo不为null,我们就插入photo信息

photo信息为null

在这里插入图片描述
说明: if标签中test属性中的photo为传递对象的属性而不是数据库表的字段

测试方法及打印结果:
在这里插入图片描述

photo信息不为null

在这里插入图片描述
在这里插入图片描述

7.2 <trim>标签

上述的<if>标签如果使用了多个,如下面这种情况
在这里插入图片描述
为了解决上述问题,我们在整个需要判断条件的语块中添加<trim>标签

关于<trim>标签的属性:

  • prefix:表示整个语句块,以prefix的值作为前缀
  • suffix:表示整个语句块,以suffix的值作为后缀
  • prefixOverrides:表示整个语句块要去除的前缀
  • suffixOverrides:表示整个语句块要去除的后缀

注意: 当trim标签里没有任何内容的时候,是不会加上前缀后缀的,只有trim里面有内容,前缀和后缀的设置才生效

我们可以调整上述xml中的sql为:

在这里插入图片描述

测试方法:

在这里插入图片描述

打印结果:

在这里插入图片描述

7.3 <where>标签

当传入对象,根据属性进行where条件筛选的时候,当属性不为null的都为查询条件

当<where>标签中有内容时候,此时sql会加上where进行条件筛选,如果无内容则不会添加where,并且<where>标签会去除前缀and(不能去掉后缀and

在这里插入图片描述

7.4 <set>标签

根据传入的对象属性来更新数据,如果<set>标签里没内容,则不生成set,当内容不为空的时候会生成set,并且<set>标签会自动去除后缀 ,不会去除前缀

    <update id="updateById">
        update user
        <set>
            <if test="username != null">
                username=#{username}
            </if>
            <if test="password != null">
                password=#{password}
            </if>
        </set>
        <where>
            <if test="id != null">
                id=#{id}
            </if>
        </where>
    </update>

7.5 <foreach>标签

对某个集合遍历可以使用该标签,该标签有如下属性:

  • collection:绑定方法中的集合对象
  • item:遍历时,集合中的每一个元素
  • open:给语句块添加前缀
  • close:给语句块添加后缀
  • separator:间隔字符串

示例:我们删除id为6,7,8,9的用户

在这里插入图片描述

测试方法:

    @Test
    void deleteByIds() {
        int[] ids = {6,7,8,9};
        int n = userMapper.deleteByIds(ids);
        System.out.println(n);
    }

打印结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/534654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“Shell“脚本命令

文章目录 一.sort命令二.uniq命令三.tr命令四.cut命令五.split命令六.paste命令七.eval命令 一.sort命令 以行为单位对文件内容进行排序&#xff0c;也可以根据不同的数据类型来排序&#xff1b;比较原则是从首字符向后&#xff0c;依次按ASCII码值进行比较&#xff0c;最后将…

“Shell“数组

文章目录 一.数组1.1数组定义的方法1.2示例在这里插入图片描述 二.数组包2.1数组包括的数据类型2.2传输数组2.3返回数组 一.数组 1.1数组定义的方法 &#xff08;30 20 10 60 50 40&#xff09; //以空格相间隔的数组0 1 2 3 4 5 //下标方法一&am…

ACL 2022 | chatglm微调神器P-Tuning v2论文学习

一、概述 title&#xff1a;P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks 论文地址&#xff1a;https://arxiv.org/abs/2110.07602 代码&#xff1a;GitHub - THUDM/P-tuning-v2: An optimized deep prompt tuning st…

ESP32 浮点性能评估

根据数据表,处理器应该包含一个硬件浮点单元: ESP32数据手册摘录 我编写了一个小测试来测量单精度(32 位)和双精度(64 位)的基本浮点运算。除了这些基本测试之外,我还测量了一个典型的小型算法的性能,该算法计算天文学中使用的本地视恒星时间。 作为参考,我在 STM32…

Apache Kafka实战:超越数据边界-Apache Kafka在大数据领域的崭新征程【上进小菜猪大数据】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 Apache Kafka 本文将介绍Apache Kafka在大数据领域的应用及其重要性&#xff0c;并提供一些代码实例来帮助读者更好地理解和应用Apache Kafka。文章主要包括以下几个方面&#xf…

GPT-2 面试题

简介 1、GPT-2 是什么&#xff1f;它是基于什么模型的&#xff1f; GPT-2 是一种人工智能的大型语言模型&#xff0c;由 OpenAI 在2019年提出。它是基于变压器&#xff08;Transformer&#xff09;模型的&#xff0c;使用了自注意力&#xff08;Self-Attention&#xff09;机…

分布式锁的实现?

分布式锁的实现&#xff1f; 答&#xff1a; 应用比较广泛&#xff1a;后台业务的防重提交 以前的传统应用用户流量比较小&#xff0c;为了节省成本&#xff0c;很多应用的成本都是单节点部署&#xff0c;为了解决单节点访问资源一致性的问题&#xff0c;对于java来说&#…

linux系统(守护进程-线程)08_守护进程,线程,线程创建,线程退出,线程回收,杀死线程,线程分离,线程属性分离

01 学习目标 1.守护进程的特点 2.熟练进行守护进程的创建 3.熟练掌握多线程的创建 4.熟练掌握线程的退出和资源回收 02 守护进程相关的概念 进程组&#xff1a;多个进程在同一个组&#xff0c;第一个进程默认是进程组的组长。 会话&#xff1a;进程组的更高一级&#xff0c;多…

二分搜索帮我解决实际问题

文章阅读 文章阅读 二分搜索代码框架常应用于「在有序数组中搜索指定元素」这个基本场景&#xff0c;具体的实际问题可以没有那么直接&#xff0c;但是也可以使用二分搜索进行解决 实际问题一般都让你求最值&#xff0c;比如让你求吃香蕉的「最小速度」&#xff0c;让你求轮船…

JavaWeb《后端内容:4. 项目实战:书城系统》

0.把之前的系统的Myssm部分封装为包 新建空的工件jar包 创建相同的文件夹&#xff0c;导入相应文件要从out里面导入字节码文件 全部设置完后点构建工件&#xff0c;然后点刚刚我们设置的这个工件&#xff0c;然后从src下的out文件相应的位置就能找到这个jar包&#xff0c;用于…

Discourse Table Builder 插件

ABC 仓库链接GitHub - discourse/discourse-table-builder: A theme component that allows for easily building and editing of markdown tables in Discourse. 概述Table Builder 这个插件能够让用户能够在 Discourse 的编辑对话框中快速的对表格进行编辑&#xff0c;同时也…

Flink学习——处理不同数据源的流数据,存入不同的Sink端

目录 一、单机版安装 二、IDEA操作Flink (一)添加依赖 (二)数据源——Source 1.加载元素数据 2.加载集合数据 3.加载文件目录 4.加载端口 5.加载kafka的topic——重要&常用 6.加载自定义数据源 (三)输出端——Sink 1.读取文件中的数据&#xff0c;处理后输出到…

ESP32设备驱动-振动电机模块驱动

振动电机模块驱动 文章目录 振动电机模块驱动1、振动电机介绍2、硬件准备3、软件准备4、驱动实现1、振动电机介绍 振动电机是用于产生振动的机械装置。 振动的产生是在驱动轴上质量不均匀的电动机的支持下发生的。 它是一种微型直流电机,通过振动让用户知道声音。 在此必须注…

《计算机网络—自顶向下方法》 Wireshark实验(五):UDP 协议分析

用户数据报(UDP)协议是运输层提供的一种最低限度的复用/分解服务&#xff0c;可以在网络层和正确的用户即进程间传输数据。UDP 是一种不提供不必要服务的轻量级运输协议&#xff0c;除了复用/分用功能和简单的差错检测之外&#xff0c;几乎就是 IP 协议了&#xff0c;也可以说它…

RabbitMQ养成记 (10.高级特性:死信队列,延迟队列)

死信队列&#xff08;DLX&#xff09; 这个概念 在其他MQ产品里面也是有的&#xff0c;只不过在Rabbitmq中稍微特殊一点 什么叫私信队列呢&#xff1f; 就是当消息成为 dead message之后&#xff0c;可以重新发到另外一台交换机&#xff0c;这个交换机就是DLX。 注意这里的有翻…

基于OpenCV的人脸检测软件(含Python源码+UI界面+图文详解)

软件功能演示 摘要&#xff1a;人脸检测的目标是找出图像中所有的人脸对应的位置&#xff0c;算法的输出是人脸外接矩形在图像中的坐标&#xff0c;可能还包括姿态如倾斜角度等信息。本文详细介绍了其实现的技术原理&#xff0c;同时给出完整的Python实现代码&#xff0c;并且通…

GeoTools实战指南: 空间坐标系-地理信息科学的核心

GeoTools实战指南: 空间坐标系-地理信息科学的核心 引言 在我们的日常生活中,地图、GPS导航和地理位置服务已经变得司空见惯。但是,你有没有想过这些工具背后的工作原理呢?它们都依赖于一种称为"空间坐标系"的关键概念。本文将深入探讨空间坐标系的基础知识和其…

多线程专题(上)学习随手笔记

JMM&#xff1a;主内存物理内存线程共享&#xff0c;工作内存CPU缓存线程独占volatile&#xff1a;可见性、禁止指令重排&#xff0c;不可保证原子性&#xff1b;用于懒汉单例模式&#xff08;双重检测&#xff09;或状态标记Synchronized&#xff1a;保证代码块或方法同步化执…

Unity的URP下使用SRPBatcher

大家好&#xff0c;我是阿赵。这里继续来讲一下URP相关的东西。 这次主要说的是SRP Batcher的使用 一、在URP下实现SRP Batcher 1、设置 在我们创建的URPAsset文件的高级选项里面&#xff0c;有一个SRP Batcher的开关&#xff0c;默认就是勾上的。 2、修改shader 在把项目转…

小白白也能学会的 PyQt 教程 —— 自定义组件 Switch Button

文章目录 前言思路讲解代码部分 前言 最近在搞 Python 课程设计&#xff0c;想要搞一个好看的 UI&#xff0c;惊艳全班所有人。但打开 Qt Creator&#xff0c;Win7 风格的复古的按钮是在让我难以下手。 其次&#xff0c;我因为想要打造一个 Fluent UI 样式的设置页面&#xff…