MySQL03


  • MySQL-多表查询

    • 概述

      • 数据准备:将资料的sql脚本导入到本地数据库(8条dept部门表数据,17条emp员工表数据)

      • 多表查询-介绍:从多张表查询

        • 查询测试数据的表,select * from tb_emp,tb_dept;会发现查询出来了85条数据,仔细看可以发现每个员工都和五个部门组合在了一次,这个现象叫笛卡尔积
      • 笛卡尔积:笛卡尔乘积是指在数学中,两个集合(A集合和B集合)的所有组合情况

        • 数据库的笛卡尔积现象:a集合每一条记录都和b集合的记录做一个匹配,总数据量就是a集合的数据量乘以b集合的数据量img

        • 在多表查询时,需要消除无效的笛卡尔积img

      • 但是实际上每个员工只能归属于一个部门,所以每五条记录只有一条记录是有效记录,其他四个都是无效记录,不需要,而多表查询就是根据业务需求查询多张表的信息,并且根据业务需要,去除掉这些无效的笛卡尔积

        • 例如要查询每个员工的信息和每个员工对应部门的信息,那我们将员工的部门id字段和部门表的id字段对应起来就可以了,而其它数据对于我们来说都是无效的笛卡尔积img

        • 所以只要加上一个连接条件,查询员工表的部门id等于部门表的id的记录,加上关键字where,后面指定连接条件img

      • 分类:

        • 连接查询

          • 内连接:相当于查询A、B交集部分数据

          • 外连接:

            • 左外链接:查询坐标所有数据(包括两张表交集部分数据)

            • 左外链接:查询坐标所有数据(包括两张表交集部分数据)img

        • 子查询:查询中又嵌套了查询

        • 图示

          • img
    • 内连接

      • 语法

        • 隐式内连接:select 字段列表 from 表1,表2 where 条件 …;

        • 显示内连接:select 字段列表 from 表1 [inner] join 表2 on 连接条件..;

      • 需求

        • 我的代码,没问题img

        • 想要员工的name字段和部门的name字段,直接写两个name,数据库不能分清是部门的名称还是员工的名字,是会报错的,此时在字段名前指定表明,比如tb_emp.name字段img

        • 一共有17条数据,只查询出来了16条,是因为有一个员工部门是null,未分配,那这条记录就是和部门表没有关联的,由于内连接查询的是两张表的交集数据,所以A表没有和B表产生关联的数据是查询不出来的imgimg

        • 显示内连接需要用inner join 要连接的表 on 连接条件:显示的声明,除此和隐式 内连接差别不大(inner可以不加)

      • 起别名:在from后面的表名空格加上别名,后面的连接条件表名和前面的表名.字段名都需要用别名代替(当表名比较长,一个个打很麻烦,这时就可以考虑起别名)img

    • 外连接

      • 语法

        • 左外连接:select 字段列表 from 表1 left [ outer ] join 表2 on 连接条件…;(表1也叫左表,表2也叫右表,左外连接会完全包含左表)

        • 右外连接:select 字段列表 from 表1 right [ outer ] join 表2 on 连接条件…;(表1也叫坐标,表2也叫右表,右外连接会完全包含右表)

      • 需求

        • 我的代码img

        • 刚才在内链接中陈友谅的部门未分配,没有和部门表产生关联,内连接查询不出来,但是外连接就可以了

        • 老师的代码第一次查询了所有员工(17条),第二次查询了所有的部门(18条==16条交集数据+包含在部门表但是员工表没有数据),还起了别名img

        • 右外连接也可以改造成左外连接,right–>左右表互调即可(也就是上图的第三条SQL语句,查询结果和第二条一样是18条,就算该部门没有员工也能查出来)

      • 左连接能查询到左表和两表交集的部分,右表也是同理。

      • 在项目开发中,通常使用左外连接,很少使用右外连接,因为右外连接可以替换成左外连接

    • 子查询

      • 介绍:SQL语句中嵌套select语句,称为嵌套查询,又称子查询。

      • 形式:select * from t1 where colum = ( select column1 from t2 … );

      • 子查询外部的语句还可以是insert / update /delete / select 的任何一个,最常见的是 select。

      • 分类

        • 标量子查询:

          • 概念:子查询返回的结果为单个值

          • 常用的操作符: = <> > >= < <=

          • 需求

            • A.查询“教研部”的所有员工信息

              • a.查询 教研部 的部门ID下的员工信息img

              • b.再查询该部门ID下的员工信息img

              • 将两条SQL语句合并为1条:直接把下面的2替换成上面的SQL语句,不过需要加上括号。可以看到效果是一样的img

            • B.查询再“方东白”入职之后的员工信息

              • 写子查询一定要考虑步骤是什么

              • a.查询方东白地入职时间

              • b.查询再“方东白”入职之后的员工信息

        • 列子查询:

          • 概念:子查询返回的结果为一列(可以为多行)

          • 常用操作符:in、not in等

          • 需求:

            • 我的代码img

            • a.查询教研部和咨询部地部门id

            • b.根据部门id,查询该部门下的员工信息

        • 行子查询:

          • 子查询返回的结果为一行(可以为多列)

          • 常用的操作符:=、<>、in、not in

          • 需求

            • 我写的img

            • a.查询”韦一笑”的入职日期及职位img

            • b.查询与其入职日期 及 职位都相同的员工信息img

            • 做替换,但是这条sql语句出现了多次子查询,性能太低,需要优化img

            • 其实and连接的两个=可以用()组合起来,不同字段用逗号分隔,就代表分别相等才成立下面两条语句是等价的img

            • 所以最优解如下img

        • 表子查询:

          • 子查询返回的结果为多行多列,常作为临时表

          • 常用的操作符:in

          • 需求

            • 我写的img

            • a.查询入职日期是“2006-01-01”之后的员工信息(这样就获得入职日期在2006-01-01之后的员工信息)img

            • b.查询这部分的员工信息及其部门名称 - tb_dept(把子查询作为临时表使用)img

    • 案例

      • 需求1

        • 我写的img

        • 如果在需求中没有说明要完全包含哪张表的数据,就用内连接就可以了

        • 老师的代码img

      • 需求2

        • 我写的img

        • 老师写的(范围闭区间可以用between)img

      • 需求3

        • 我写的img

        • 老师写的(查询每个分类最贵的菜品,所以对分类进行分组,而且分组后的字段包括分组字段加上聚合函数)(没有特殊说明,直接用内连接)img

      • 需求4

        • 我写的(这里本来是想写d.name,但是后来发现c.named.name效果一样)img

        • 老师写的(老师在查询两个表时用连接条件消除了无效的笛卡尔积查询,关键字“各个分类”,“总数量”–>分组查询,聚合函数统计,老师直接使用count(*)统计了分组后查询个数)img

      • 需求5

        • 我写的img

        • 老师写的:需要查询三张表,菜品表,套餐表和他们的中间关系表,不管查询多少张表,都可以用隐式内连接的方式,from后面加上表名就可以了,后面加上where指定连接条件消除无效数据(和我写的一模一样的)img

      • 需求6

        • 我写的img

        • 老师写的(计算所有菜品平均价格就不需要分组和指定分组条件了)

          • 合并后(子查询)img
      • 写需求的时候:1.先去分析这个需求涉及的表结构有哪些2.分析这两张表的数据,联查的时候他们的联查条件是什么,分析完这两点后再来完成SQL语句的编写

    • tip:子查询的效率并不高,能使用连接查询代替子查询,尽量使用连接查询

    • 小结img

  • MySQL-事务

    • 业务场景(只是假设,真实情况解散部门可能不会删员工)

      • 模拟解散部门:执行部门和部门关联的员工就没了img

      • 测试异常情况:删除部门3及员工,但第二个SQL语句=变为==,执行,然后第二条SQL语句报错,结果是部门没了,但员工还在,此时就会出现数据不一致的情况(3号部门员工有但没有3号部门)img

      • 思考&解决:想解决这类问题就可以借助数据库的事务img

    • 事务介绍

      • 概念:事务是一组操作的集合,他是一个不可分割的工作单位。它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

      • 比如:刚才刚才执行解散部门的业务时涉及到两个操作:1.删除部门2.删除部门下的员工,由于它们属于删除部门这一个业务,那这两个操作就是一个不可分割的单位,所以它就属于一个事务,那里面涉及到的操作要么同时成功,要么同时失败

      • 刚刚案例出现的问题:删除部门成功了,删除部门员工信息却失败了,为什么?

      • 注意事项:默认MySQL的事务时自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务(也就是说刚才执行的delete语句分别是两个事务)

      • 解决:将两步操作控制在一个事务范围内,将涉及到数据库中的事务控制

    • 操作:事务控制

      • 开启事务:short transaction; / begin;(这组事务都提交成功后才能提交事务)

      • 提交事务:commit;(把这次所执行的这些操作真正的提交到数据库来修改表结构中的数据)

      • 回滚事务:rollback;(当这组操作有任何一个操作失败,此时就要回滚事务,把数据恢复到之前的样子)

      • 开启事务后再执行SQL语句不会真正改变表结构:

        • 代码img

        • 表结构没有发生变化imgimg

        • 但是查询后发现3号部门及其员工都已经被删除,只不过这个操作还没正式提交,所以在别的窗口中看到的这个数据依然是存在的,因为这个事务和别的窗口其实也相当于是一个事务,它是相互隔离的imgimg

      • 只有在提交事务后表结构才会发生变化,就能在别的窗口看到了(正常情况)

        • imgimg
      • 异常情况测试:删除2号部门及员工,但删部门有语病

        • 这时候会出现一个SQL语句的报错,这时候不能再执行commit操作了,因为commit是所有操作都执行成功之后再执行的提交事务img

        • 只要有一个操作执行失败,我们要执行的是rollback回滚事务

        • 在这之前,先执行两条语句查询一下两张表的表结构,可以看到2号部门删了,但2号部门员工没有删imgimg

        • 执行回滚事务后再次查询部门表,发现2号部门恢复过来了img

      • 这样就可以在发现一旦出现异常之后,我们就可以通过rollback将删除的数据再恢复过来,从而保证了操作前后数据是一致的,这就是事务,一组操作要么同时成功,要么同时失败

    • 四大特性(ACID,首字母缩写)

      • 原子性(Atomicity):事务是不可分割的最小单元,要么全部成功,要么全部失败。

      • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态(完成–>提交/回滚)

        • 比如说:刚刚的部门和员工都删掉了或者部门和员工都没删,但是部门删了员工没删就叫数据不一致了
      • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响下的独立环境运行

        • 比如说刚刚只要事务还没提交,窗口中的表结构就不会发生变化,这就是隔离性的体现

        • 而这个隔离性我们可以通过隔离级别设置,隔离性越高,事务越安全,但是效率也就越低

      • 持久性(Durability):事务一旦提交或回滚,他对数据库中的数据的改变就是永久的

        • 一个事务提交或是回滚了,把数据库关闭了,下次打开,数据库仍旧是提交或者回滚后的数据
    • 小结img

  • MySQL-索引

    • 索引-介绍:

      • 现象:查询一条记录,耗时了十三秒多

        • 原因:这张表的数据量比较大,可以用count(*)查询记录条数:600万,一旦某张表的数据量变大,它的查询效率也会变低,数据量越大,查询数据越低img

        • 优化以提升查询效率:为skn表的sn字段建立索引就好了,一次性将600万个数据的索引创建建好了,耗时了45秒(不用每次都构建),之后在查询只用了6ms,将查询速度提升了几千倍,这就是索引的魅力img

      • 概念:索引(index)是帮助数据库高效获取数据的数据结构。

      • 没有索引的查询方式:拿着查询数据和所有数据一个个进行比较,在没找到的情况下从头找到尾,也称之为全表扫描(效率低,而且数据量越大,查询效率越低)img

      • 有索引的情况:为age字段建立一个索引,他就会维护一个索引对应的数据结构,提高查询效率(比如说二叉搜索树:第一个数放根节点,比根节点大的数放在右边,比根节点小的数放在左边,以此提升查询效率)(真正的索引结构不是这个样子,这只是一个示意图)img

      • 索引的优点(简单来说就是提升查询和排序的效率)

        • 1.提高数据查询的效率,降低数据库的IO成本。

        • 2.通过索引对列数据进行排序,降低数据排序的成本,降低CPU消耗

      • 索引的缺点

        • 1.索引会占用存储空间

          • 在mysql中的数据存放目录,其解压目录下的data目录就是数据库的数据文件,里面每一个文件夹就对应一个数据库,一个数据库里的文件就对应一张表,数据库db04中有tb_sku这张表,数据库文件中也会有tb_sku.ibd这个文件,这个文件存放的就是这张表对应的的数据以及索引的信息img
        • 2.索引大大提升了查询效率,同时却也降低了insert、update、delete的效率。

          • 增删改使数据发生变化了,就需要重新维护这个索引的数据结构,这就会降低增删改的效率,比如说插入age88,在索引结构也要增加88这个节点
      • 但是在优点面前,这两个缺点就可以忽略不计了

        • 1.因为对现在的企业来说,这个磁盘空间就不用多虑了,而且索引本身所占的磁盘空间也不会很大

        • 2.对于一个正常的业务系统来说,查询会占到90%以上,增删改的频率本来就很低了,所以在业务操作时我们主要考虑的时查询性能的优化

    • 索引-结构:

      • MySQL数据库支持的索引结构有很多,如:Hash索引、B+Tree索引、Full-Text索引等。我们平常所说的索引,如果没有特别指明,都是指默认的B+Tree结构组织的索引。

      • 二叉搜索树当中,左子树的所有数据都是小于根节点的,右子树的所有数据都是大于根节点的,而且根节点的左右两个子树又都是一个二叉搜索树。那它就很容易出现偏向一边的情况,如果保存数据时是跟数据数据的从大到小或从小到大来保存的,那就会将二叉树绘画成一个单向列表,此时它的性能就会大打折扣,此时可以用平衡二叉树或者红黑树(也是平衡二叉树)来解决这个问题。img

      • 但MySQL数据库没有采用平衡二叉树和红黑树作为索引结构,因为它们在大数据量情况下,会出现层级深,检索速度慢的问题(一个结点只能有两个子节点,大数据量情况下必然会加深树的速度,查询速度就会变慢)

      • B+Tree(多路平衡搜索树)

        • 特点:1.每个节点都能存储多个key,不像二叉树,每个结点只能存储两个key,B+树中,存储了多个key,就会有多个key的指针,每一个指针会指向一个磁盘块(也叫页:数据库进行磁盘管理的最小单位,一个页的大小是16kb)

        • 有n个key,就会有n个指针,就会有多个子节点,这多个子节点也就是我们所说的多路

        • 2.最底下这层我们称之为叶子节点,而上面两层称之为非叶子节点,B+树中的非叶子节点仅仅起到索引数据查找数据的作用,它并不保存数据,所有的数据都是在叶子节点部分(绿色部分)来保存的,所有的key也都会出现在叶子节点,比如说根节点的key:6、28、67,在叶子节点中都有img

        • 3.由于B+树是一个多路平衡搜索树,所以他的叶子节点元素都是按照元素的从小到大的顺序来排序的,而且叶子节点形成了一个双向链表,我们可以由上一个元素找到下一个元素,由下一个元素找到上一个元素

        • B+树的数据查询:比如说53,1.首先和根节点进行对比,在与根节点进行对比时,内部会采用二分查找的方式来进行操作,直接定位53在38到67的区间范围内(53>=38 & 53<67),所以它会走p2这个指针,p2指向中间的磁盘块,2.之后它会在查找这个磁盘块的数据,再来对比53在哪个区间范围之内,是介于44到59这个范围内的,之后他又会走这个磁盘块中的p2这个指针,而这个指针又指向下面这个磁盘块,所以又会到下面的磁盘块来寻找,最终找到这个磁盘块中的53并获取到对应的数据img

        • 再比如说查询29:[6,38)–>p1–>[29,…)–>p3–>最终定位到29和29对应的数据(此时发现只需要进行三次io就能查找到数据)img

        • 总结:1.每一个结点可以有n个key,n个key对应n个指针,n个指针意味着一个结点可以有多个子节点,相对于红黑树/平衡二叉树,相同数据量的情况下,它的树的高度就会低的多,所以mysql中的B+树的索引,最终形成的是一个矮胖矮胖的树,树的层级可能在3-4层 2.不管查找哪条数据,都要找到叶子结点才能拿到对应的数据,这样就能保证数据库服务器的查询性能比较稳定3.叶子节点的元素形成了一个有序的双向列表,便于数据的排序和区间范围的查询

    • 索引-语法:

      • 创建索引:create [ unique ] index 索引名 on 表名(字段名,……);(指定为哪张表的哪些字段创建索引xx,如要创建唯一索引,需要在index前加上unique)

        • 索引名的一般命名规范:idx_emp(表名)_name(字段名)
      • 查看索引:show index from 表名;(查看这张表的所有索引信息)

        • 查询出来3个索引:1.第一个是id,是这张表的主键,一旦指定了id是某一张表的主键,它就会自动创建一个索引,我们叫它主键索引,而且主键索引的性能是最高的2.第二个建立索引的字段是username,这个索引建立的原因是我们之前给这个字段添加了唯一约束,一旦我们指定这个字段是唯一的,他就会为这个字段创建一个唯一索引(unique index),所以添加唯一约束本质上是添加了一个唯一索引img
      • 删除索引:drop index 索引名 on 表名;(删除这张表的这个索引)

      • 代码

        • img
      • 注意事项

        • 主键字段,在建表时,会自动创建主键索引。

        • 添加唯一约束时,数据库实际上会添加唯一索引

    • 小结img

  • MyBatis-入门

    • 什么是MyBatis?

      • MyBatis是一款优秀的持久层框架,用于简化JDBC的开发(持久层就是web开发三层架构中的dao数据访问层:与数据库打交道的)

        • JDBC:sun公司提出的JavaEE13项规范之一,是sun公司提供的用来操作数据库的一套规范,但是直接使用底层的JDBC来操作数据库会非常繁琐,现在基本上使用的都是Mybatis这样的框架来简化JDBC的开发
      • MyBatis本是Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。

      • 官网:https://mybatis.org/mybatis-3/zh/index.html

    • MyBatis课程学习安排

      • 三个部分:1.通过入门程序体验MyBatis是如何操作数据库的和MyBatis的开发流程2.MyBatis基础增删改查(基本功,项目中使用频次最高)3.Mybatis的高级科技:动态SQL。我们直接使用SpringBoot去整合MyBatis(因为现在企业中绝大部分的项目都是基于SpringBoot构建的,这也是且也开发中最为普遍,最为主流的方式)
    • MyBatis-快速入门程序

      • 需求:使用Mybatis查询所有用户数据

      • 图形化界面查询:执行select * from user;

        • img
      • 其实Mybatis和图形化界面查询的底层逻辑是一样的

        • 图形化工具操作数据库:在图形化界面编写SQL语句,然后将这条sql语句发送给数据库服务器来执行,数据库再将结果返回给图形化界面工具img

        • 而MyBatis操作数据库其实就是在Java程序中来编写这条SQL语句,然后将这条sql语句发送给数据库执行,数据库再将结果返回给Java程序img

      • 步骤

        • 1.准备工作(创建springboot工程、数据库表user、实体类User)

          • 实体类表是用来封装用户信息的,在图形化界面工具,数据库会将查询结果返回,之后工具再以表格的形式呈现出来,而在Java程序中,SQL语句执行完毕后,会将结果返回给Java程序,那Java程序就要将返回的结果封装起来,其中返回的每个数据我们都会将其封装为User对象,表中的字段最终会自动封装到对象当中,所以在入门程序中建议命名属性名时和字段名保持一致,这样框架就可以完成自动封装
        • 2.引入Mybatis的相关依赖,配置Mybatis

          • 因为我们现在操作的是MySQL数据库,所以引入的依赖除了Mybatis框架(MyBatis Framework)还有MySQL的驱动(MySQL Driver),那将来如果操作的时Oracle,那就得引入Oracle的驱动,由于我们创建的是SpringBoot工程,所以只要在创建工程时勾选mybatis的依赖和mysql驱动的依赖就可以了,配置MyBatis还要配置数据库连接信息

          • 图形化界面连接数据库:点击database菜单的+号,选择要链接的数据库(mysql),看似很多,其实只有四项:

            • 1.Driver:指定数据库驱动类的类名,如果要连接的是MySQL数据库,那这个类名是固定的,就是com.mysql.cjjdbc.Driver(点进去蓝色带下划线的MySQL)img

            • 2.数据库连接的URL:这个url前面的部分:jdbc:mysql://,这一部分是固定的,是协议部分,协议之后的部分指定我们当前要链接的是哪一个数据库服务器,localhost代表的是本机,3306指定的是数据库服务器的端口号,后面加上/mybatis代表我们要连接的是这个数据库服务器当中的哪一个数据库,mybatis是一个数据库的名字(图形化界面为了让信息展现的更加直观,操作的更加方便,将url中的主机地址,端口号以及数据库的名字这三个部分又单独的在上面展示出来了,分别是host,port,database)img

            • 3+4:User和Password:数据库访问的用户名和密码

          • Mybatis操作数据库的方式和图形化工具操作数据库的方式底层是一样的,所以在Mybatis操作数据库时,也需要配置数据库连接的这四项信息:驱动器的全类名,数据库的url,用户名和密码。这四样信息也称为数据库连接的四要素,由于我们使用的是SpringBoot整合MyBatis,所以这四项信息需要配置在springboot默认的配置文件appplication.properties,而properties的配置方式就是key=value,等号之前是属性名,等号之后是属性值

        • 3.编写SQL语句(注解/XML)

          • 方式1:基于注解来定义(入门阶段采用)

            • 按照MyBatis的规范,我们需要定义一个接口叫UserMapper,并且在接口上加上@ Mapper注解来表示当前接口时Mybatis当中的一个持久层的接口(三层架构中的数据访问层:dao层的接口,也可以叫userdao,但是在Mybatis当中,我们一般都叫Mapper,所以也叫Mapper接口),然后再再接口当中加上一个注解@Select,来指定当前是一个查询操作,再在注解当中指定要执行的SQL语句,而最终我们想要执行这条SQL语句,只要执行UserMapper的list()方法即可,此时框架就会自动执行这条SQL语句,并将SQL语句的查询结果封装到方法的返回值中
          • 方式2:基于XML来定义

        • 图示

          • img
        • 说明:在MyBatis的开放中,只需要定义Mappper接口就可以了,不需要定义其实现类,因为程序在运行时,框架底层会自动生成这个接口的实现类对象

      • 操作思维导图Day08MySQL-多表查询MySQL-事务MySQL-索引MyBatis-入门什么是MyBatis?MyBatis课程学习安排MyBatis-快速入门程序需求:使用Mybatis查询所有用户数据图形化界面查询:执行select * from user;其实Mybatis和图形化界面查询的底层逻辑是一样的步骤

        • 1.file,new moudle,spring initializr,填写Group组织名(com.itheima)、Artifact模块名(springboot-mybatis-quickstart),包名后面不需要删掉,老师用的是11,Location是创建目录,确认没有问题后,点击next,这里可以选择springboot的版本,老师使用的是当时最新版2.7.5,Dependencies的SQL栏下直接选择MyBatis相关依赖(MyBatis Framework和MySQL Driver),点击finish后他就会自动联网创建并下载相关依赖,保留src文件夹和pom.xml,其他删掉,保持工程的简洁img

        • 双击pom文件查看引入进来的依赖:首先,所有的springboot项目都有一个父工程,其中指定了springboot的版本1.mybatis-spring-boot-starter:mybatis的起步依赖2.mysql-connector-j:mysql驱动包(这是刚刚发布的最新版本的驱动包,后面的项目开发中可能会用到的另外一个驱动包:坐标的组织名是mysql,ArtifactID是mysql-connecter-java,它是上一个版本的驱动包,现在的项目当中普遍使用的这个驱动包)3.spring-boot-starter-test:springboot单元测试img

        • 创建user表,在资料里

        • com.itheima下创建pojo.User类,连包带类一次创建,pojo包专门来存放实体类,其中的属性定义与表的字段名一致,而且需要private私有化封装,推荐使用包装类,unsigned tinyint在Java中使用Short接收即可,之后再为这些字段生成getter和setter方法,还要toString方法,还要有参无参构造,快捷键生成即可(我用PTG To JavaBean)img

        • 配置数据库的连接信息-四要素(比较固定,可以直接复制资料信息),在sec的resources的application.properties里(数据库名字和用户密码要改成自己的)

          • img
        • 创建mapper包(层)和UserMapper接口img

        • UserMapper接口

          • img
        • 按照标准的maven的项目结构来说,单元测试的代码不应该写在main目录下而在test目录下,test目录底下有个springboot工程创建好自带的类,是一个测试类,这个类上面有一个注解@SpringBootTest :springboot整合单元测试的注解,接下来我们就可以在这个类做一个单元测试,定义方法public void testListUser()查询全部用户信息,上面加上注解@Test ,这里就可以调用UserMapper的list方法来查询全部用户信息了,但UserMapper是一个接口,不能直接new,但是此前提到过,@Mapper 注解能生成接口的实现类对象并将其交给IOC容器管理,他已经成为IOC容器中的Bean了,在单元测试中通过依赖注入即可将这个Bean对象注入进来,所以只需在测试类当中声明一个UserMapper类型的对象,在上面加上注解@Autowired 来完成依赖注入

        • 之后就可以直接调用UserMapper的list方法来查询所有用户信息,将返回值以stream流的形式来遍历输出出来,由于这个单元测试是springboot整合的单元测试,上面加了一个注解,@SpringBootTest ,一旦加了这个注解,这个单元测试方法在运行的时候就会自动加载整个springboot环境,并且创建springboot的IOC容器,IOC容器创建好了,接下来我么们就可以通过依赖注入的形式从IOC容器中获取UserMapper类型的Bean对象,接下来就可以调用UserMapper的list方法来查询全部用户信息了

        • 代码及正确输出六条用户信息的结果

          • img
      • 配置SQL语句编写提示

        • 情形:刚刚编写的sql语句在IDEA只是一个字符串,没有任何对错相关的提示,一旦出错就会报错,对开发人员极不友好

        • 解决:配置SQL提示(23版自带,不用配)

          • 图示img
        • 但是写表名的时候不会指定表名,或者表名爆红

          • 产生原因:Idea和数据库没有建立连接,不识别表信息img

          • 解决方式:在Idea中配置MySQL数据库连接

        • 解决:与指定的数据库建立连接

          • 选择database菜单,加号,选择数据源datasource,连接SQL数据库,写上用户名密码和连接的数据库即可(可以刷新数据库)img
        • 我又指定了数据库是mysql,勾选了一个id才显示的表名

        • 现在就可以只输id打出罗列的全部字段了

          • img
        • 这样编写的SQL语句有问题编码阶段就知道了,就不用等到查询运行才发现了,降低了程序出错概率,提升了开发效率

    • JDBC介绍

      • 将mybatis与jdbc对比,看看mybatis到底简化了哪些jdbc的操作

      • JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API

      • Java想要操作MySQL,ORACLE这些数据库,就得通过Sun公司提供的gdbc这套API来操作,而关系型数据库有很多,不同的数据库底层实现也有非常大的差异,底层实现的方式不同,sun公司提供的操作所有关系型数据库的api-jdbc是如何实现的呢?因为sun公司提供的仅仅是一套规范,一套接口而已,它并没有提供具体的实现,而由各个数据库厂商提供接口的实现,一个数据库的底层细节和实现方式厂商最清楚,比如mysql提供mysql的实现,而我们最后操作数据库,提供jdbc提供的接口就可以了,其实就是依靠各个尝试提供的jdbc接口的实现来操作对应的数据库,它们这些实现也叫驱动,比如刚刚入门程序引入的mysql驱动,他就是mysql厂商提供的jdbc的实现

        • img
      • jdbc实现

        • 演示:代码很多imgimg
      • 连接的url,username,password容易变动,但打包好的java代码变动极不方便2.代码繁琐3.释放资源

        • img
      • mybatis怎么解决这些问题:配置在appllication.properties的配置文件中了,以后配置这块信息就不用配置java代码,直接操作配置文件就好了2.mybatis自动把查询结果封装到集合中去了,查询返回的每一条记录都会返回为一个user对象,而所有的对象都会封装到list集合中,整个过程自动化,不用谢繁琐的获取代码了3.在application.properties中配置数据库连接信息时,所有的配置项前缀都是spring.datasource,datasource翻译过来叫数据源,按这种方式连接数据库,springboot底层会自动采用数据库连接池技术来统一管理和分配这些连接,这个连接指的就是connection对象,有了连接池之后要获取对象,只需要在连接池获取一个连接,然后执行sql语句,这条sql语句执行完之后,再将这个链接归还给连接池,这样就能做到连接的复用,避免了频繁的获取连接,释放连接而造成的资源浪费

        • img
      • 使用mybatis只要关注application.properties和mapper接口就行了

    • 数据库连接池

      • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)(类似线程池)

      • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

      • 释放空间时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

      • 没有连接池,客户端执行SQL语句是怎样的

        • 1.首先创建一个新的连接对象

        • 2.执行SQL语句

        • 3.关闭连接对象释放资源

        • 每一次都要开启一次连接,用完之后又要把这个连接关了,比较浪费资源

      • 有了数据库连接池:

        • 1.程序在启动时就会初始化一定数量的连接对象

        • 2.客户端再在执行sql语句时就会从连接池来获取一个连接

        • 3.获取到连接后,就会执行sql语句,sql语句执行完后,会再把连接归还给连接池

        • 这样就做到了连接的复用,而不是每次都创建一个新的连接

      • 连接池还有一个功能

        • 客户端执行sql语句时,他会从连接池获取相关连接,sql语句执行完之后,再把连接归还给连接池,但如果有个别客户端获取了这个连接,这个连接是空闲状态,也就是说这个连接并没有去访问数据库,此时连接池就会检测这个连接的空闲时间,如果说这个空闲时间超过了数据库连接词当中预设的最大时间,这个连接就会释放归还给连接池,这样就可以解决某一些连接没有及时释放而导致数据库连接池当中的连接越用越少,这样就会有一个问题,再过来一个客户端发现没有连接池可用的连接,那他就会被遗漏,不被分配连接的问题
      • 优势:

        • 资源重用

        • 提升系统响应速度(创建连接比较消耗资源

      • 实现数据库连接池

        • 标准接口:DataSource

          • 官方提供的数据库连接池接口,由第三方组织实现此接口

          • 功能:获取连接–Connection getConnection() throws SQLException;(关键方法)

        • 连接池产品

          • C3P0、DBCP(现在项目开发用的少)

          • Druid德鲁伊(阿里巴巴开源的数据库连接池项目,功能强大,性能优秀,是java语言最好的数据库连接池之一)

          • Hikari追光者(springboot默认),性能很高

            • 刚刚程序中出现的输出日志有img

            • 双击打开了源码,所有数据库连接池都实现了这个sun公司提供的DataSource接口img

        • 切换连接池:引入德鲁伊连接池的起步依赖(在资料里拿到坐标放入pom,刷新即可)

          • 1img

          • 再次执行,发现控制台输出日志的连接池改变,说明连接池切换成功,img

          • 双击搜索,点击源码,右击空白处,选择Diagrams->show diagram,发现他也实现了DataSource接口,因为所有连接池都必须要实现这个标准接口(我没有)img

          • 方式2:添加droid,也可以参考官方文档img

        • 小结

          • img
    • lombok


文章作者: Ceasteo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ceasteo !
评论
  目录