• 7.MyBatis 操作数据库(初阶)


    文章目录

    大家好,我是晓星航。今天为大家带来的是 MyBatis 操作数据库(初阶) 相关的讲解!😀

    1.什么是MyBatis

    MyBatis 是⼀款优秀的持久层框架,它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了⼏ 乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注解来配置 和映射原始类型、接⼝和 Java POJO(Plain Old Java Objects,普通⽼式 Java 对象)为数据库中的 记录。

    简单来说 MyBatis 是更简单完成程序和数据库交互的⼯具,也就是更简单的操作和读取数据库⼯具。

    Mybatis官⽹

    2.为什么要学习 MyBatis?

    对于后端开发来说,程序是由以下两个重要的部分组成的:

    1. 后端程序
    2. 数据库

    ⽽这两个重要的组成部分要通讯,就要依靠数据库连接⼯具,那数据库连接⼯具有哪些?⽐如之前我们 学习的 JDBC,还有今天我们将要介绍的 MyBatis,那已经有了 JDBC 了,为什么还要学习 MyBatis? 这是因为 JDBC 的操作太繁琐了,我们回顾⼀下 JDBC 的操作流程:

    1. 创建数据库连接池 DataSource

    2. 通过 DataSource 获取数据库连接 Connection

    3. 编写要执⾏带 ? 占位符的 SQL 语句

    4. 通过 Connection 及 SQL 创建操作命令对象 Statement

    5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值

    6. 使⽤ Statement 执⾏ SQL 语句

    7. 查询操作:返回结果集 ResultSet,更新操作:返回更新的数量

    8. 处理结果集

    9. 释放资源

    MyBatis 可以看作是Java程序和数据库之间的桥梁,具体实现还是mysql实现的(jdbc)

    访问数据库,还是MySQL实现的

    3.通过spring框架创建MyBatis项目

    创建mybats-demo项目

    image-20240319182711588

    添加插件时记得加上Lombok、Spring Web、Mybatis Framework

    image-20240319182730438

    3.1使用MyBatis查询数据库

    创建好后,我们小试牛刀,先编写一个 select * from student 查询代码

    image-20240319190834026

    写入连接数据库的包结构

    引入依赖

    image-20240321092044957

    UserInfo.java:

    image-20240319190951966

    将数据库中的接收元素对应定义好,定义在类UserInfo中

    userInfoController.java:

    image-20240319191005151

    使用userInfoController来完成引用userInfoMapper对象调用其selectAll()方法,并返回取出来的数据表的值,保存在目录 http://127.0.0.1:8080/selectAll

    UserInfoMapper.java: (接口 - 写 MyBatis 代码)

    image-20240319191037287

    数据库接口 操作数据库代码

    application.yml: (配置文件 - 配置数据库)

    image-20240319191935765

    将idea与数据库连接起来

    注:这里3306后面跟的test1就是我们要链接的数据库中的数据库,下面的username和password为各位的账号密码,密码默认为空或root。

    MybatisDemoApplication.java: (启动类)

    image-20240319191148568

    在启动类中执行MyBatis代码,运行连接数据库

    网页访问返回值:

    image-20240319192300630

    与mysql数据库中查询返回值对比:

    image-20240319192455102

    举例2:

    image-20240321095142061

    这里的@Param注解用处:

    @Param的作用就是给参数命名,比如在mapper里面某方法A(int id),当添加注解后A(@Param(“userId”) int id),也就是说外部想要取出传入的id值,只需要取它的参数名userId就可以了。将参数值传如SQL语句中,通过#{userId}进行取值给SQL的参数赋值。

    image-20240321095243362

    3.2 mysql连接不上报错解决方法

    博主这里一开始全是报错,直接四个error

    application.yml

    image-20240319193317550

    在搜寻了大量资料后,发现只需要在pom.xml中加入一个依赖即可轻松解决

            <dependency>
                <groupId>com.mysqlgroupId>
                <artifactId>mysql-connector-jartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4

    如果明确知道自己的版本还可以在下面写上自己的版本便于精确下载

            <dependency>
                <groupId>com.mysqlgroupId>
                <artifactId>mysql-connector-jartifactId>
                <version>x.x.xversion>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.MyBatis的基础操作

    4.1企业建表规范:

    image-20240319200951908

    哪怕表里只有一个字段,比如userid,也需要加上这三个字段

    image-20240319201013447

    逻辑删除和物理删除

    逻辑删除:指从逻辑上进行数据删除

    物理删除:从硬盘上进行数据删除

    4.2MyBatis基本实现

    1.引入Mybatis依赖, 引入对应数据库的依赖,比如mysql

    2.配置数据库相关信息

    3.定义Java对象

    4.写实现

    image-20240319194137272

    4.3单元测试

    在需要写单元测试的类中,点击右键选择Test

    image-20240319202158581 image-20240319202242777

    点击玩Test会出现一个选项框:

    image-20240319202403776

    按照上图选择

    image-20240319202453133

    自动生成了一个 UserInfoMapperTest.java 类

    测试文件位置:

    image-20240319203230346

    补充代码

    image-20240319203201620

    点击运行:

    image-20240319203302594

    解析代码:

    image-20240319203515641

    4.4使用MyBatis可能遇到的问题

    1.没有配置数据库相关信息

    image-20240319203708371

    2.账号密码错误

    image-20240319203730316

    image-20240319203754035

    3.数据库错误

    image-20240319203841997

    image-20240319203907370

    4.表不存在

    image-20240319204017915

    image-20240319204033345

    5.字段错误

    image-20240319204050912

    image-20240319204123959

    如何避免这些错误呢?

    建议能复制就复制,不要背,少用手敲,手敲很容易就敲错代码

    4.5配置MyBatis相关日志

    application.yml

    image-20240319204641779 image-20240319204737009

    image-20240319204800830

    4.6打印MyBatis的日志配置

    image-20240321093124160

    在关键信息节点打印日志 - 与个人经验有关

    image-20240321093143233

    image-20240321093148185

    4.7MyBatis增删查改 - 注解方式

    4.7.1增加

    4.7.1.1插入数据

    UserInfoMapper.java:

    image-20240321101309252

    test中的测试代码:

    image-20240321101231985

    运行idea:

    image-20240321101431328

    查看数据表数据:

    image-20240321101529906

    可以看到id为17,name为小蓝,gender为男的数据已经成功添加进来了。

    4.7.1.2如何获得自增ID

    image-20240321102149080

    image-20240321102218768

    idea打印结果:

    image-20240321102256213

    代码解析:

    image-20240321102332451

    4.7.1.3参数为对象时,对参数进行重命名

    image-20240321103157850

    使用@Param之后,运行报错,找不到username

    image-20240321103245711

    此时我们就需要调用userInfo来找里面的username,password,age,gender,phone这些数据表定义字段

    4.7.2删除

    4.7.2.1删除数据

    UserInfoMapper.java:

    image-20240321104519907

    test中的测试代码:

    image-20240321104508451

    删除前:

    image-20240321105502003

    删除后:

    image-20240321104451207

    返回值为1:

    image-20240321104551166

    4.7.3更改

    4.7.3.1更改数据

    UserInfoMapper.java:

    image-20240321105732522

    test中的测试代码:

    image-20240321105746695

    更改前:

    image-20240321105455898

    更改后:

    image-20240321105817961

    更改成功后返回Update值为1,并返回数据修改成功:

    image-20240321105923143

    4.7.4查询

    4.7.4.1查询数据 (与3.1一致)

    创建好后,我们小试牛刀,先编写一个 select * from student 查询代码

    image-20240319190834026

    写入连接数据库的包结构

    引入依赖

    image-20240321092044957

    UserInfo.java:

    image-20240319190951966

    将数据库中的接收元素对应定义好,定义在类UserInfo中

    userInfoController.java:

    image-20240319191005151

    使用userInfoController来完成引用userInfoMapper对象调用其selectAll()方法,并返回取出来的数据表的值,保存在目录 http://127.0.0.1:8080/selectAll

    UserInfoMapper.java: (接口 - 写 MyBatis 代码)

    image-20240319191037287

    数据库接口 操作数据库代码

    application.yml: (配置文件 - 配置数据库)

    image-20240319191935765

    将idea与数据库连接起来

    注:这里3306后面跟的test1就是我们要链接的数据库中的数据库,下面的username和password为各位的账号密码,密码默认为空或root。

    MybatisDemoApplication.java: (启动类)

    image-20240319191148568

    在启动类中执行MyBatis代码,运行连接数据库

    网页访问返回值:

    image-20240319192300630

    与mysql数据库中查询返回值对比:

    image-20240319192455102
    4.7.4.2如果mysql字段名和Java对象的属性不一致
    4.7.4.2.1对mysql查询结果进行重命名

    结果映射

    Mybatis 会自动的根据数据库的字段名和Java对象的属性名,进行映射

    如果名称一样,就进行赋值

    image-20240321110151200

    image-20240321110655612

    4.7.4.2.2使用@Results注解
    • property 属性:指定 Article 中对应的属性,即⽤户。
    • resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织⽤户数据。
    • columnPrefix 属性:绑定⼀对⼀对象时,是通过columnPrefix+association.resultMap.column 来映射结果集字段。 association.resultMap.column是指 标签中 resultMap属性,对应的结果集映 射中,column字段。

    image-20240321111025267

    如果字段和Java属性名称一样,可以省略

    image-20240321111044592

    4.7.4.2.3自动转驼峰

    image-20240321111134111

    4.8传递参数

    image-20240321151230668

    image-20240321151235387

    image-20240321151244324

    以上为xml和注解通用的知识

    5.学习XML

    5.1学习xml的方式

    1.配置数据库

    2.指明xml的路径

    image-20240321141654068

    3.写xml的实现

    image-20240321141659815

    image-20240321142401659

    5.2xml常见问题

    image-20240321142511854

    可能原因:

    1.xml和接口定义的方法名称不一致

    2.mapper的路径配置和xml的路径不一样

    3.xml namespace写错了

    5.3xml实现增删查改

    5.3.1增

    image-20240321143551541

    5.3.2删

    image-20240321143745117

    5.3.3改

    image-20240321143758630

    5.3.4查

    image-20240321143830141

    5.4如果mysql字段名和Java对象的属性不一致

    1)给字段设置别名

    2)通过标签来实现

    3)自动转驼峰

    6.其他查询操作

    6.1多表查询

    多表查询和单表查询类似,只是SQL不同而已

    工作中尽量避免多表查询,尤其是对性能要求非常高的项目(多表查询比较慢)

    image-20240321153042620

    上面为单表查询,下面为多表查询

    1)通常情况下,数据库集群 是很多项目一起使用的,当出现慢查询时,会影响整个集群,也就是会影响所有使用该集群的项目

    2)Java服务器扩容更方便
    数据库集群扩容需要DBA来处理

    image-20240321160134608

    SQL中直接查询多个表,把查询的结果放在一个对象即可

    6.2#{}和${}

    使用#查询

    image-20240321160253997

    image-20240321160704373

    使用$查询

    image-20240321160301695

    image-20240321160713535

    两者区别:

    使用 #时, 如果参数为String, 会自动加上’’

    $ 不会,$符号是直接 拼接

    如果是字符串类型,需要加上"

    6.3排序功能

    6.3.1 SQL中Group by排序讲解:

    image-20240321193825922

    6.3.1.1sum + group by:

    image-20240321192926316

    image-20240321193839188

    6.3.1.2avg + group by:

    image-20240321193357323

    image-20240321193832521

    6.3.1.3max + group by

    image-20240321194905320

    image-20240321193825922

    6.3.1.4min + group by

    image-20240321194849935

    image-20240321193825922

    6.3.1.5Where + group by

    image-20240321193550734

    image-20240321193825922

    6.3.1.6having + group by

    image-20240321194021756

    image-20240321193825922

    6.3.1.7where + having + group by

    image-20240321194047694

    image-20240321193825922

    6.3.1.8count + group by

    image-20240321195012380

    image-20240321193825922

    6.3.1.9 min+max+sum+avg+count()+group by+having+as

    这次我们换个表来个大杂烩

    image-20240321195115287

    由图可以表名为score

    image-20240321195359662

    这张表中我们按照stu_id来分组,分别查询并展示了(按顺序写的)最小值、最大值、累加值、平均值、记录数并为他们加上了as取了别名

    6.3.2代码排序

    image-20240321201648768

    image-20240321201713020

    image-20240321201729395

    6.3.3SQL注入问题(重点)

    SQL注入(SQL lnjection)是发生在Web程序中数据库层的安全漏洞,是比较常用的网络攻击方式之一,他不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至修改数据库。也就是说,SQL注入就是在用户输入的字符串中添加SQL语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的SQL语句就会被数据库服务器误认为是正常的SQL语句而运行,攻击者就可以执行计划外的命令或者访问未授权的数据。

    image-20240321203350034

    如果用这条语句,那么无论""中为什么,or1=1一定为真,那么就会绕过语句直接拿到表中的信息

    6.3.3.1恶意拼接

    SQL语句可以对数据进行增删改查,且使用分号来分隔不同命令。例如:

    SELECT * FROM user WHERE user_id = $user_id
    
    • 1

    其中user_id是传入的参数,如果传入参数的值为"1234;DELETE FROM user",那么最终执行的查询为:

    SELECT * FROM users WHERE user_id = 1234; DELETE FROM users
    
    • 1

    如果执行以上语句,则会删除user表中的所有数据

    6.3.3.2利用注释执行非法命令

    SQL语句中可以插入注释,例如

    SELECT COUNT(*) AS 'num' FROM score WHERE id=24411 AND version=$version
    
    • 1

    如果version包含了恶意的字符串" ‘-1’ OR 3 AND SLEEP(500) ",那么最终查询的语句会变为

    SELECT COUNT(*) AS 'num' FROM score WHERE id=24411 AND version='-1' OR 3 AND SLEEP(500)
    
    • 1

    以上恶意查询只是想耗尽系统资源,SLEEP(500) 将导致 SQL 语句一直运行。如果其中添加了修改、删除数据的恶意指令,那么将会造成更大的破坏。

    6.3.3.3传入非法参数

    SQL 语句中传入的字符串参数是用单引号引起来的,如果字符串本身包含单引号而没有被处理,那么可能会篡改原本 SQL 语句的作用。 例如:

    SELECT * FROM user_name WHERE user_name = $user_name
    
    • 1

    如果 user_name 传入参数值为 G’chen,那么最终的查询语句会变为:

    SELECT * FROM user_name WHERE user_name ='G'chen'
    
    • 1

    一般情况下,以上语句会执行出错,这样的语句风险比较小。虽然没有语法错误,但可能会恶意产生 SQL 语句,并且以一种你不期望的方式运行。

    6.3.3.4添加额外条件

    在 SQL 语句中添加一些额外条件,以此来改变执行行为。条件一般为真值表达式。例如:

    UPDATE users SET userpass='$userpass' WHERE user_id=$user_id;
    
    • 1

    如果 user_id 被传入恶意的字符串“1234 OR TRUE”,那么最终的 SQL 语句会变为:

    UPDATE users SET userpass= '123456' WHERE user_id=1234 OR TRUE;
    
    • 1

    如果执行以上语句,将更改所有用户的密码

    6.3.4如何避免SQL注入

    1.避免使用动态SQL
    避免将用户的输入数据直接放在SQL语句中,最好使用准备好的语句和参数化查询,这样更安全。

    2.不要将敏感数据保留在纯文本中
    加密存储在数据库中的私有/机密数据,这样可以提供了另一级保护,以防攻击者成功的排出敏感数据

    3.限制数据库的权限和特权
    将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作

    4.避免直接向用户显示数据库错误
    攻击者可以使用这些错误消息来获取有关的数据库信息。

    6.3.5mybatis中#和$的区别(重点)

    image-20240321203451293

    #没有SQL注入问题,而$要考虑SQL注入问题

    image-20240322154153223

    1、在MyBatis 的映射配置文件中,动态传递参数有两种方式:

    image-20240321202645424

    2、#{} 和 ${} 的区别

    (1)

    image-20240321202730266

    (2)

    image-20240321202813848

    (3)

    image-20240321202819056

    (4)

    image-20240321202823725

    (5)

    image-20240321202828731

    6.3.6MyBatis是如何防止SQL注入的

    MyBatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己手动编写,这个时候当然需要防止SQL注入。其实,MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构,参考上面的两个例子。其中,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。回应上文,如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中使用#的即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:

    select id, username, password, role from user where username=? and password=?
    
    • 1

    不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。

    【底层实现原理】MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译

    6.4like 查询

    image-20240321201834589

    image-20240321201915594

    image-20240321201729395

    7.数据库连接池

    上述代码我们使用了数据库连接池奇数,避免频繁的创建链接,销毁链接

    7.1介绍

    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个.

    image-20240322161045732

    没有使用数据库连接池的情况:每次执行SQL语句,要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行完,再关闭连接对象释放资源,这种重复的创建连接,销毁连接比较消耗资源

    使用数据库连接池的情况: 程序启动时,会在数据库连接池中创建一定数量的Connection对象,当客户请求数据库连接池,会从数据库连接池中获取Connection对象,然后执行SOL,SOL语包执行完,再把Connection归还给连接池,

    优点:

    1. 减少了网络开销
    2. 资源重用
    3. 提升了系统的性能

    7.2使用

    常用的数据库连接池:

    • C3P0
    • DBCP
    • Druid
    • Hikari

    取maven仓库中查找依赖:

    image-20240322162438102

    image-20240322162500372

    image-20240322162553197

    引入依赖:

    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druid-spring-boot-starterartifactId>
        <version>1.1.17version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    image-20240322162620914 image-20240322162636825

    点击刷新一下,即可自动下载对应的依赖包

    感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

  • 相关阅读:
    [干货满满] 三年经验前端的面试经验分享
    2023.09.30使用golang1.18编译Hel10-Web/Databasetools的windows版
    时间序列中的6大类10种异常值处理方法(从根源上提高预测精度)
    数商云:供应商多场景趋势下,服装企业如何打造灵活应用的SRM管理体系?
    Java8新特性
    【FLink】Flink 任务 如何优雅的停止
    Definition and properties of the Gamma function
    Session会话追踪的实现机制
    Vue 中 v-if 和 v-show 有什么区别?
    判断二叉树是否是平衡二叉树(c#)
  • 原文地址:https://blog.csdn.net/xinhang10/article/details/138201409