GULI PART.1
文章目录
- 1、尚硅谷-谷粒学院
- 1.1、系统功能模块介绍
- 1.2、系统开发方式
- 2、Mybatis-Plus
- 2.1、什么是 MyBatis?
- 2.2、什么是Mybatis-Plus?
- 2.3、Mybatis-plus 的特性
- 2.4、支持的数据库
- 3、Mybatis-Plus入门
- 3.1、创建表和数据
- 3.2、创建SpringBoot工程
- 3.3、安装Mybatis-Plus
- 3.3.1 问题:pom依赖显示红色,无法更新依赖
- 3.3.2 安装Lombok插件
- 3.4 、配置application.properties
- 3.5、实体类的编写
- 3.6、创建Mapper接口
- 3.7、测试
- 3.8、Mybatis-plus的日志打印
- 4、Mybatis实现CRUD
- 4.1、实现添加功能
- 4.1.1、主键的生成策略
- 自动增长
- UUID
- Redis实现
- Mybatis-Plus中自带的策略
- 3.9.2、配置主键生成策略
- 4.2、实现更改数据
- 4.2.1、自动填充
- 4.3、实现简单查询
- 4.4、实现逻辑删除
- 4.4.1、物理实现
- 4.4.2、批量删除
- 4.4.3、条件删除
- 4.4.3、逻辑删除
- 5、乐观锁与悲观锁
- 5.1、事务的隔离性
- 5.2、乐观锁
- 5.3、悲观锁
- 5.4、配置乐观锁
- 配置类
- 6、分页查询
- 6.1、配置分页插件
- 6.2、编写分页代码
- 7、性能分析插件
- 8、实现复杂查询
- 9、mybatis-plus实现自定义XML查询
1、尚硅谷-谷粒学院
1.1、系统功能模块介绍
后台系统:1、讲师管理2、课程分类管理3、课程管理1.视频管理4、视频信息统计分析5、订单管理6、轮播图banner管理7、权限管理前台系统:1、首页数据的显示2、讲师列表和详情3、课程列表和课程的详情1.课程详情2.课程观看3.课程评论4、登录和注册1.微信扫码登录5、微信扫码支付
1.2、系统开发方式
前后端分离开发
全栈开发后端技术:SpringBoot、SpringCloud、SpringSecurity、Redis、Maven、EasyExcel、Jwt、Oauth2
前端技术:Vue、Element-UI、axios、node.js
其它技术:阿里云OSS,阿里云视频点播、阿里云短信服务、微信支付和登录、docker、jenkins、git
2、Mybatis-Plus
2.1、什么是 MyBatis?
https://mybatis.net.cn/getting-started.html
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
2.2、什么是Mybatis-Plus?
https://baomidou.com/pages/24112f/
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
2.3、Mybatis-plus 的特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
2.4、支持的数据库
MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库
3、Mybatis-Plus入门
3.1、创建表和数据
表和数据的脚本来源于Mybatis-plus的官网,来自快速开始。
#创建表
DROP TABLE IF EXISTS user;
CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
);DELETE FROM user;
#插入数据
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
3.2、创建SpringBoot工程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-87gCXMkO-1690788257982)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805092526643.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-akmT3Fgl-1690788257987)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805092625620.png)]
视频中使用的版本是2.2.1,最好选择稳定版本,不要选择最新的版本,这里我选择2.7.2版本的SpringBoot,是稳定版
3.3、安装Mybatis-Plus
在pom文件中,写入以下的依赖。
如果出现依赖无法加载的情况,请更新maven的镜像库(阿里云的比较好)。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--Mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency>
<!--lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency>
<!--数据库连接包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.19</version></dependency></dependencies>
3.3.1 问题:pom依赖显示红色,无法更新依赖
提示信息:
No valid Maven installation found. Either set the home directory in the configuration dialog or set the M2_HOME environment variable on your system.没有找到 可用的maven 安装设置。要么在配置对话框中设置主(home)目录或者在你的系统上设置M2_HOME环境变量。Either...or... 要么...要么...configuration 配置dialog 对话
原因:
IDEA的Maven地址设置出错,找不到指定的maven路径
解决方案:在IDEA中配置好Maven的位置,包括setting.xml和repository的位置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTHY01b3-1690788257992)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805094250837.png)]
https://blog.csdn.net/Julycaka/article/details/83185621
3.3.2 安装Lombok插件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RP8acKdP-1690788257997)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805095431661.png)]
插件里面搜索Lombok,安装
3.4 、配置application.properties
application.yaml或者application.properties都可以
src/ main/ resources
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisstudy?serverTimezone=GMT
spring.datasource.username=root
spring.datasource.password=li1473606768
3.5、实体类的编写
使用Lombok,减少代码量。
@Data会给该类的所有私有属性自动添加Get和Set方法。
@AllArgsConstructor是有参,@NoArgsConstructor是无参
实体类User
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dtCjW2zE-1690788258002)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805100429878.png)]
3.6、创建Mapper接口
使接口类继承BaseMapper
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AuZulL2T-1690788258006)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805100834752.png)]
继承之后,按住Control点击BaseMapper这个类,就可以看到里面自动生成的方法。
然后我们还需要对SpringBoot的启动类添加一个MapperScan的注解,注解的参数为实际放置Mapper的包的路径:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IThr9Op4-1690788258011)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805101028092.png)]
@Repository是sping注解需要配合@MapperScan使用,@Mapper是mybatis注解可以单独使用
3.7、测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XnTmiHZN-1690788258016)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805101641707.png)]
如果注入的userMapper出现红色波浪线提示,则可以在userMapper类中声明@Repository或者@Service将这个类声明为一个Bean对象
/*** @discription 查看数据库中user表的数据* @author Macieserenity* @updateTime 2022/8/5 11:33 * @return * @throws */@Testvoid contextLoads() {//查询user中的所有数据List<User> users=userMapper.selectList(null);System.out.println("============查询");System.out.println("users==>"+users);}
运行test类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-99MzZPU7-1690788258020)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805101921958.png)]
[User(id=1, name=Jone, age=18, email=test1@baomidou.com),
User(id=2, name=Jack, age=20, email=test2@baomidou.com),
User(id=3, name=Tom, age=28, email=test3@baomidou.com),
User(id=4, name=Sandy, age=21, email=test4@baomidou.com),
User(id=5, name=Billie, age=24, email=test5@baomidou.com)]
3.8、Mybatis-plus的日志打印
在application.properties文件中加入:
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CGfgsrdU-1690788258025)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805112630879.png)]
使用select * 的话会降低效率
https://blog.csdn.net/jiangchao858/article/details/115676371
4、Mybatis实现CRUD
4.1、实现添加功能
/*** @discription 往数据库中添加一条记录* @author Macieserenity* @updateTime 2022/8/5 11:32 * @return * @throws */@Testvoid addUser(){User user =new User();user.setAge(18);user.setEmail("hello@123.com");user.setName("makabaka");int result=userMapper.insert(user);System.out.println("============插入");System.out.println("insert==>"+result);}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JmxCaPgb-1690788258030)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805113608121.png)]
可以看到我们没有设置User 的id属性,但是查看日志可以看到,Mybatis-Plus自动为我们生成了19位Long主键的值。
4.1.1、主键的生成策略
注意:3.5版的mybatis-plus 已经将ID_WORKER改名叫ASSIGN_ID了
自动增长
Auto_increment
缺点:很难进行分表分库存储,要进行分表存储时,需要得到上一张表的长度,在此长度上+1,作为当前表的起始ID
UUID
每次生成一个随机且唯一的值
缺点:无法进行排序,
Redis实现
redis生成ID,由于redis是单线程的,可以生成全局唯一的ID,可以用redis的原子操作INCR和INCRBY来实现。
Mybatis-Plus中自带的策略
雪花算法
生成一个long型的ID,使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit是机器的ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID)。
最后一个是符号位,永远是0。
3.9.2、配置主键生成策略
在实体类的id属性上增加一个
@TableId(type=IdType.AUTO)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RYN4kO69-1690788258034)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805114937801.png)]
注意:3.5版的mybatis-plus 已经将ID_WORKER和ID_WORKER_STR改名叫ASSIGN_ID了
然后按住control键,点击AUTO,进入查看里面的策略
AUTO:主键字段自增
实体类的主键字段的注解 @TableId(type = IdType.AUTO);
数据表对应的字段一定也要设置成自增;
如果只加了注解,但没有将数据表对应的主键字段设置为自增,则将会出现如下的异常!NONE:未设置主键
由于每一张数据表都是有主键的,因此几乎没有添加该注解的必要。INPUT:需要开发者手动赋值
INPUT 如果开发者没有手动赋值,则数据库通过设置自增方式给主键赋值(MP不介入主键生成),同样地,如果数据库也没有设置自增则会抛出异常;如果开发者手动赋值,则直接存入该值。ASSIGN_ID:MyBatis-Plus 自动赋值
ASSIGN_ID 如果用户或开发者没有为主键赋值,则由 MyBatis-Plus 采用 snowflake 算法(也被称为雪花算法)为主键字段分配一个ID,这个 ID 可以是 Number(Long) 类型,也可以是 String 类型。ASSIGN_UUID:MyBatis-Plus 分配 UUID,必须是 String 类型
ASSIGN_UUID 的用法与 ASSIGN_ID 类似,可以表示更长的唯一的 ID,但其主键的数据类型必须是 String,由 MyBatis-Plus 自动生成 UUID 进行赋值;
雪花算法:snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为 毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味 着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯 一!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPhKOrAh-1690788258039)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805115030254.png)]
参考文章:
https://blog.csdn.net/m0_61961937/article/details/126048049
https://blog.csdn.net/qq_41775769/article/details/123045089
4.2、实现更改数据
/*** @author Macieserenity* <br/>* Update 更新数据*/
@Test
void updateUser(){User user =new User();user.setId(2L);user.setAge(18);user.setEmail("hello@123Update.com");user.setName("makabaka");int result=userMapper.updateById(user);System.out.println("update result==>"+result);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REtTAH1D-1690788258044)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805132726484.png)]
4.2.1、自动填充
往表中添加两个字段
#在表user中添加create_time date类型 和 update_time date类型两个字段.mysql> alter table user add create_time date;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> alter table user add update_time date;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
在实体类中添加对应的属性
注意命名的特点
在java中,使用驼峰式命名:createTime
在数据库中,不区分大小写,所以用下划线分割两个单词:create_time
手动填充方式:
@Test
void addUserDate(){User user =new User();user.setAge(22);user.setEmail("hello@123.comMakabaka");user.setName("makabakaUpdateDate");//手动添加时间user.setCreateTime(new Date());user.setUpdateTime(new Date());int result=userMapper.insert(user);System.out.println("============插入");System.out.println("insert==>"+result);
}
Mybatis-plus:自动填充
不需要手动set值,使用mybatis-plus框架的方式
//第一步:在实体类里面使用注解声明为自动填充
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xD8lgqet-1690788258048)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805134140700.png)]
或者可以把updateTime的自动填充类型设置为
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-elJU9x49-1690788258053)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805134229981.png)]
这样,在插入和更新的时候,就会自动进行填充。
//第二步:创建类实现(implement)接口MetaObjectHandler
//实现insertFill和updateFill两个方法
//在类上添加@Component声明为Spring组件,交由Spring管理
//目录:
package com.study.mybatisplusstudy.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;import java.util.Date;
/*** className: MyMetaObjectHandler<br/>* author: MacieSerenity<br/>* date: 2022-08-05 13:44<br/>**/
public class MyMetaObjectHandler implements MetaObjectHandler {/*** discription 在insert语句执行时,对设定的属性进行自动填充 <br/>* author Macieserenity <br/> * param: metaObject <br/>* updateTime 2022/8/5 13:55 <br/>* return <br/>* throws <br/>*/@Overridepublic void insertFill(MetaObject metaObject) {//第一个参数:数据库中需要自动填充的字段,取Java实体类的属性名称作为参数//第二个参数:需要填充的数据//第三个参数:源数据this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}/*** discription 在进行数据的更新时,进行数据的自动填充 <br/>* author Macieserenity <br/> * param: metaObject <br/>* updateTime 2022/8/5 13:58 <br/>* return <br/>* throws <br/>*/@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updateTime",new Date(),metaObject);}
}
然后使用test类,进行测试
//
@Test
void addUserDate(){User user =new User();user.setAge(22);user.setEmail("hello@123.comMakabaka");user.setName("makabakaUpdateDate");int result=userMapper.insert(user);System.out.println("============插入");System.out.println("insert==>"+result);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8O6NO8eh-1690788258058)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805141705861.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dDjCKTi3-1690788258063)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805141641874.png)]
4.3、实现简单查询
/*** @discription 查看数据库中user表的数据* @author Macieserenity* @updateTime 2022/8/5 11:33 * @return * @throws */@Testvoid contextLoads() {//查询user中的所有数据List<User> users=userMapper.selectList(null);System.out.println("============查询");System.out.println("users==>"+users);}
@Test
void selectUserById(){//通过ID查询User userById = userMapper.selectById(1555455304972189698L);//通过ID批量查询List<User> users1 = userMapper.selectBatchIds(Arrays.asList(1555455304972189698L, 1555437406157303809L, 1555436878589341698L));System.out.println("userById===>"+userById);System.out.println("users1===>"+users1);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9DoXYCgp-1690788258068)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805155131130.png)]
根据Map实现条件查询:
@Test
void selectUserByMap(){HashMap<String,Object> map=new HashMap<>();map.put("name","Helen");map.put("age",18);List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gk2mS6c7-1690788258073)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805155545943.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOCD7kII-1690788258079)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805155557911.png)]
4.4、实现逻辑删除
4.4.1、物理实现
/*** discription 删除ID为1555396057806725121的用户 <br/>* author Macieserenity <br/> <br/>* updateTime 2022/8/5 14:44 <br/>* return <br/>* throws <br/>*/
@Test
void deleteUser(){User user =new User();user.setId(1555396057806725121L);int result = userMapper.deleteById(user);System.out.println("delete result==>"+result);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3VrFHTDw-1690788258084)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805144411160.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cjNu5pYX-1690788258089)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805144435406.png)]
4.4.2、批量删除
同时删除多条记录@Test
void deleteMultiple(){
int result = userMapper.deleteBatchIds(Arrays.asList(1,2));
}
4.4.3、条件删除
@Test
void deleteByMap(){HashMap<String,Object> map=new HashMap<>();map.put("name","Helen");map.put("age",18);int result = userMapper.deleteByMap(map);
}
根据map进行条件删除
4.4.3、逻辑删除
原理:在表中做一个标志位,更改标志位,select时将该标志位标记为已删除的记录不可见或者跳过,完成逻辑删除。
该插件默认0没有删除,1删除
可以到配置文件中进行更改
mybatis-plus.global-config.db-confg.logic-delete-value=1
mybatis-plus.global-config.db-confg.logic-no-delete-value=0
第一步:在数据库中添加deleted字段
alter table user drop column deleted;
alter table user add deleted int default 0;
第二步:在实体类对应的属性上添加注解
@TableLogic
@TableField(fill=FieldFill.INSERT)
需要增加的语句:
//---User.java
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;//---MyMetaObjectHandler.java
this.setFieldValByName("deleted",1,metaObject);
加上逻辑删除的插件:
mybatis-plus 3.5版本及以上,就不需要配置插件了
只需要在实体类中使用对应的组件和创建数据库时添加对应的字段即可
详情:
https://blog.csdn.net/qq_57581439/article/details/124050671
第三步:测试
@Test
void logicDelete(){int i = userMapper.deleteById(1555437406157303809L);System.out.println(i==1?"删除了":"删除了但是没完全删除");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REcjlvqz-1690788258094)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805165252612.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxdfpN2h-1690788258099)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805165403779.png)]
此时我们进行查询:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1r8iIFSu-1690788258105)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805165515044.png)]
查看日志文件可以知道,自动为我们过滤了被逻辑删除的查询
//注意
//一旦加上了逻辑删除插件,mybatis-plus将无法查询到被逻辑删除的数据(即便加了deleted=1)
//只能使用xml文件,自定义一个SQL语句进行查询。
5、乐观锁与悲观锁
5.1、事务的隔离性
是为了解决 丢失更新 问题事务的隔离性:脏读 不可重复读
不可重复读和幻读是初学者不易分清的概念,总的来说,解决不可重复读的方法是 锁行,解决幻读的方式是 锁表。
事物的隔离性:
#读未提交:read uncomitted(最低的隔离级别)什么是读未提交?事务A可以读取到事务B未提交的数据。这种隔离级别存在的问题就是:Dirty Read 脏读现象读到了脏数据例如:有事务A和事务B都有以下DML语句:更新,查询,更新,查询...假设事务A和B并行执行,且我们这种隔离级别都试了理论上的,大多数的数据库隔离级别都是在 第二个读已提交 级别之后的。
#读已提交:read committed什么是读已提交?事务A只能读到事务B提交之后的数据。这种隔离级别解决了脏读现象。不可重复读数据。事务在开启之后,第一次和第二次读取的数据可能不会相同,所以不可重复读。这种隔离级别是比较真实的数据,每次读取的都是绝对的真实数据。例如:事务A和事务B 两个事务中都有多条DML语句如下:插入,查询,插入,查询...当事务A和事务B并行执行时,我们假设事务A在事务B执行到一半时提交了那么事务B的第二次读取就能读取到事务A已经提交的数据,而第一次读取到的也还是事务A未更改之前的数据。只能读取到已经提交的数据oracle数据库默认的隔离级别就是 read committed
#可重复读:repeatable read什么是可重复读?事务开启之后,无论多久,在事务A中读取到的数据都是一致的,即使事务B已经将数据修改且提交了,但是事务A读取到的数据还是不会发生改变,这就是可重复读。解决了不可重复读数据的问题。但是会产生幻影读(每一次读取的数据都是幻象,不够真实)。
#序列化/串行化:serializable (最高的隔离级别)什么是序列化?是最高级别的隔离,效率最低,解决了所有的问题。这种隔离级别表示事务排队,不能并发。synchronize,线程同步(事务同步)每一次读取到的数据都是最真实的,且效率最低。
5.2、乐观锁
取出记录时记录版本号,执行事务完毕后确定当前数据版本号是不是读取时候的版本,修改后版本相同时,更改版本号,若版本号不同,则回滚。异步,支持并发
场景:抢票系统,只能有一个人能抢到
5.3、悲观锁
串行,同步阻塞
5.4、配置乐观锁
在表中添加一个version字段,作为乐观锁的版本字段
alter table user add version int;
然后在实体类中添加version注解:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-koHiv39X-1690788258110)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805152722808.png)]
这里TableField跟上面一样,插入时赋值为1
配置类
配置类是springBoot提供的一个专门用于配置的类,使用@Configuration注解声明,为的是避免启动类中有过多的配置方法,可以讲这些配置方法专门写入一个配置类中,方便管理。
配置一个乐观锁插件
我们新建一个包叫做config里面存我们的配置类,我们可以把刚才写在主入口函数上的MapperScan一起写到该配置类中,然后将从官网找到乐观锁插件(记得要比对自己的Mybatis-Plus的版本号,它不同版本的插件好像有略微不同)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jmH6AcGH-1690788258115)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805153308864.png)]
//可以从官方网站copy下来
https://baomidou.com/pages/0d93c0/#optimisticlockerinnerinterceptor@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}
此时我们编写一个测试类
注意:必须先查再改
@Test
void testVersion(){User user = userMapper.selectById(1555455304972189698L);user.setAge(2000);userMapper.updateById(user);
}
然后我们可以通过select数据库中的数据查看执行前和执行后的数据变化:
可以看到version变化了,age变成了2000
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HnEcm3sK-1690788258120)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805154515922.png)]
6、分页查询
与pageHelper类似
6.1、配置分页插件
https://baomidou.com/pages/97710a/#%E5%B1%9E%E6%80%A7%E4%BB%8B%E7%BB%8D//以下代码写在配置类当中
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//增加一行 : 添加分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;
}
6.2、编写分页代码
new page对象,传入两个参数
当前页
页面大小
然后调用Mybatis-Plus的方法进行分页。
@Testvoid pagenation(){/*** 创建page对象* 传入两个参数:当前页和每页显示记录条数*/Page<User> page=new Page<>(1,3);/*** 使用方法:* 调用Mybatis-plus的分页查询方法,进行底层的封装* 将数据封装到page对象里面*/userMapper.selectPage(page,null);/*** 获取分页的当前页*/System.out.println(page.getCurrent());/*** 获取每页的list数据*/System.out.println(page.getRecords());/*** 获取表中的总记录数*/System.out.println(page.getTotal());/*** 获取总页数*/System.out.println(page.getPages());/*** 是否有下一页*/System.out.println(page.hasNext());/*** 是否有上一页*/System.out.println(page.hasPrevious());
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D48iUGqe-1690788258125)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220805162524854.png)]
@Bean public MybatisPlusInterceptor pageinationinterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor// 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = falseinterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor; } 查找问题的时候看到的,虽然跟我这个问题不是特别有关系,但是可能以后有用?https://blog.csdn.net/m0_49513507/article/details/124200458
7、性能分析插件
/**
* dev 开发环境
* test 测试环境
* prod 生产环境
*/
//该插件 3.2.0 以上版本移除推荐使用第三方扩展 执行SQL分析打印 功能
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor performanceInterceptor=new PerformanceInterceptor();performanceInterceptor.setMaxTime(100);//超过100msSQL语句不执行performanceInterceptor.setFormat(true);return performanceInterceptor;
}
配置spring的环境:
在application.properties中添加:
spring.profiles.active=dev
8、实现复杂查询
@Test
void testWrapper(){QueryWrapper<User> wrapper=new QueryWrapper<>();//通过QueryWrapper设置条件//ge,gt,le,lt 大于等于、大于、小于等于、小于//示例:查询age>=30的wrapper.ge("age",10);//eq 等于 ne 不等于wrapper.ne("name","lucy");//betweenwrapper.between("age",20,30);//like 模糊查询wrapper.like("email","test");//oderByDescwrapper.orderByDesc("id");//last 拼接到语句最后 尽量不要用wrapper.last("limit 1");//指定要查询的列wrapper.select("id","name");List<User> users = userMapper.selectList(wrapper);System.out.println(users);}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hdEUo5zi-1690788258130)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220806100639243.png)]
9、mybatis-plus实现自定义XML查询
首先写一个Mapper类继承BaseMapper类
项目目录结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0pWlAik-1690788258134)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220806111820748.png)]
package com.study.mybatisplusstudy.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.study.mybatisplusstudy.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;/*** @className: UserMapper* @Author: yeyulemon* @Date: 2022-08-05 10:06**/
@Repository
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 也可以不用配置XML直接使用注解的方式实现
// @Select("select * from user where id = #{id}")
// User findSomeone(@Param("id") Long Id);//声明一个方法findSomeoneUser findSomeone(@Param("id") Long Id);
}
一定要记得在配置类或者是启动类加伤MapperScan,扫描mapper
@Configuration
@MapperScan("com/study/mybatisplusstudy/mapper")
public class MyConfig {...
}
然后我们在resources文件夹下,创建一个文件夹,来存储我们的xml文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ur46o7sn-1690788258139)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220806111701212.png)]
还有就是在application.properties文件中,配置好对应的mapper.xml的位置,用于扫描mapper
#确定位置#
mybatis-plus.mapper-locations=classpath:/mybatisMapper/*Mapper.xml
#日志#
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.mybatisplusstudy.mapper.UserMapper"><resultMap id="userMap" type="com.study.mybatisplusstudy.entity.User"><id column="id" property="id" /><result column="name" property="name" /><result column="age" property="age" /><result column="email" property="email" /><result column="create_time" property="createTime" /><result column="update_time" property="updateTime" /><result column="version" property="version" /><result column="deleted" property="deleted" /></resultMap><select id="findSomeone" resultMap="userMap">select id,name,age,email,create_time,update_time,version,deleted from user where id = ${id};</select>
</mapper>
我们在xmlwen文件中一定要声明mapper的namespace,指定为刚刚创建的接口类(路径一定要选择正确)
然后是如果是查询语句,我们需要写一个对应的resultMap来指定查询结果中实体类与数据库中数据的对应关系
例如:数据库中查询出来的列名叫做create_time,找到实体类中对应的名称(一般是驼峰命名法)crateTime进行绑定
如上resultMap所示。
绑定完成之后,要在对应的select语句后面使用resultMap指定返回值的绑定关系。
之后,我们编写测试类来测试
/*** discription 自定义XML方式实现SQL查询 <br/>* author Macieserenity <br/> <br/>* updateTime 2022/8/6 11:23 <br/>* return <br/>* throws <br/>*/
@Test
void testXmlSQL(){User selectUser =userMapper.findSomeone(1L);System.out.println(selectUser);
}
不同于默认配置,这里的SQL日志打印出来之后是直接带着数据的,没有进行prepare预处理
预处理: where id = ?
这里没有进行预处理?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KiOY7g10-1690788258143)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220806112538208.png)]
原因是因为我们在xml中的select语句中使用的$符号而不是#号,此时我们将xml文件中的select语句进行修改:
<select id="findSomeone" resultMap="userMap">select id,name,age,email,create_time,update_time,version,deleted from user where id = #{id};
</select>
注意,这里我们之前使用的是id = ${id} 此时我们将其改为 where id = #{id},再次执行测试类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iseyszhr-1690788258148)(%E5%B0%9A%E7%A1%85%E8%B0%B7-%E8%B0%B7%E7%B2%92%E5%AD%A6%E9%99%A2%E9%A1%B9%E7%9B%AE.assets/image-20220806112844194.png)]
可以看到,SQL语句正常的执行了预处理,其参数变成了 ?
返回的数据:
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=null, updateTime=null, version=null, deleted=0)
相关文章:
GULI PART.1
文章目录 1、尚硅谷-谷粒学院1.1、系统功能模块介绍1.2、系统开发方式 2、Mybatis-Plus2.1、什么是 MyBatis?2.2、什么是Mybatis-Plus?2.3、Mybatis-plus 的特性2.4、支持的数据库 3、Mybatis-Plus入门3.1、创建表和数据3.2、创建SpringBoot工程3.3、安装…...
NetApp FAS2750 和 FAS2820:适用于分布式企业和从远程到核心的 FAS
NetApp FAS2750 和 FAS2820:适用于分布式企业和从远程到核心的 FAS 拥有分布式企业和多个办公位置的客户希望使用这些系统进行虚拟化,以及为大型 FAS 和 AFF 系统提供简单且经济高效的备份和灾难恢复。 为什么要从 NetApp FAS 系列中选择一个型号&…...
剑指YOLOv8改进最新MPDIoU损失函数:超越现有多种G/D/C/EIoU,23年7月首发论文,高效准确的边界框回归的损失
💡本篇内容:剑指YOLOv8改进最新MPDIoU损失函数:超越现有多种G/D/C/EIoU,23年7月首发论文,高效准确的边界框回归的损失 💡🚀🚀🚀本博客 改进源代码改进 适用于 YOLOv8 按步骤操作运行改进后的代码即可 💡:重点:该专栏《剑指YOLOv8原创改进》只更新改进 YOLO…...
SQL-每日一题【1070. 产品销售分析 III】
题目 销售表 Sales: 产品表 Product: 编写一个 SQL 查询,选出每个销售产品 第一年 销售的 产品 id、年份、数量 和 价格。 结果表中的条目可以按 任意顺序 排列。 查询结果格式如下例所示: 示例 1: 解题思路 前置知…...
为何押注AI大模型的微软云,业绩增速反而不如谷歌云?
科技云报道原创。 上周微软、谷歌、Meta等国外科技公司相继发布最新财报。作为与人工智能、云计算和数字广告等领域相关的巨头,它们的一举一动都将对市场产生影响,同时也吸引着众多从业者的关注。 在国外三大云巨头中,谷歌云的市场份额长期…...
CDN加速服务的工作原理
CDN(内容分发网络)加速服务是一种用于提高网站和应用性能的技术,通过将内容分发到全球多个节点,使用户可以从就近的节点获取所需内容,从而实现更快的加载速度和更稳定的访问体验。下面详细介绍CDN加速服务的工作原理&a…...
在CSDN学Golang云原生(Kubernetes Service)
一,service的定义与基本用法 在 Kubernetes 中,Service 是一种抽象概念,用于定义一组 Pod 并为它们提供访问入口。通过 Service,您可以将多个 Pod 组合成一个逻辑单元,并使用标签选择器来确定哪些 Pod 属于该 Service…...
【数据结构篇C++实现】- 图
友情链接:C/C系列系统学习目录 文章目录 🚀一、图的基本概念和术语1、有向图和无向图3、基本图和多重图4、完全图5、子图6、连通、连通图和连通分量7、强连通图、强连通分量8、生成树、生成森林9、顶点的度、入度和出度10、边的权和网11、稠密图、稀疏图…...
Sentinel持久化规则
项目中有用到Sentinel,然后需要将Sentinel上配置的规则做持久化(或者初始化),通过改写Sentinel源码实现了需求,下面记录一下实现过程。 如果不知道Sentinel怎么搭,可以看看: 流控平台Sentinel搭建和接入教程_东皋长歌的博客-CSDN博客 一,背景 Sentinel是Alibaba开源…...
list与sort()
运行代码: //list与sort() #include"std_lib_facilities.h" //声明Item类 struct Item {string name;int iid;double value;Item():name(" "),iid(0),value(0.0){}Item(string ss,int ii,double vv):name(ss),iid(ii),value(vv){}friend istre…...
6个月、21天,GoldenDB分布式数据库核心系统落地中移动
近日,2023“鼎新杯”数字化转型应用大赛入围名单公示,山东移动基于GoldenDB分布式数据库的CRM&BOSS核心系统自主创新实践成功入选。该项目是中兴通讯与中国移动在数据库关键领域的又一个合作范例。 核心系统业务量大,分布式转型迫在眉睫 …...
如何正确培养数据思维?
在大数据时代,数据思维已成了每个人的必备品。下面,我们就来了解一下,什么是数据思维。不过要想弄懂什么是数据思维,首先来打破大家对数据的错误认知,数据不仅仅指数字。 1. 数据思维是什么? 百度百科对数…...
JavaScript中的?.和??的用法
1、?.(可选链运算符) 在JavaScript中,"?.“是一种叫做"Optional Chaining”(可选链)的新操作符。它允许我们在访问一个可能为null或undefined的属性或调用一个可能不存在的方法时,避免出现错误…...
Git for linux
<1> linux 安装git sudo apt-get install git-all <2> 创建git,分为两部分,远程网络部分和本地主机部分 远程网路:登录GitHub: Let’s build from here GitHub 注册帐号,创建登录密码,此密码很长&a…...
uniapp小程序,根据小程序的环境版本,控制的显页面功能按钮的示隐藏
需求:根据小程序环境控制控制页面某个功能按钮的显示隐藏; 下面是官方文档和功能实现的相关代码: 实现上面需要,用到了uni.getAccountInfoSync(): uni.getAccountInfoSync() 是一个 Uniapp 提供的同步方法,…...
kotlin 编写一个简单的天气预报app(二)增加搜索城市功能
增加界面显示openweathermap返回的信息。 在activity_main.xml里增加输入框来输入城市,在输入款旁边增加搜索按钮来进行查询。 然后原来显示helloworld的TextView用来显示结果。 1. 增加输入城市名字的EditText <EditTextandroid:id"id/editTextCity"…...
【分布鲁棒、状态估计】分布式鲁棒优化电力系统状态估计研究[几种算法进行比较](Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
vue中的require
vue中的require 一、基本概念二、具体演示1.引入json2.引入图片 三、require.context引入图片:引入json引入模块js:引入vue文件: 一、基本概念 require 是 node 中的一个方法,他的作用是 用于引入模块、 JSON、或本地静态文件。r…...
Linux进程间共享内存通信时如何同步?(附源码)
今天我们来讲讲进程间使用共享内存通信时为了确保数据的正确,如何进行同步? 在Linux中,进程间的共享内存通信需要通过同步机制来保证数据的正确性和一致性,常用的同步机制包括信号量、互斥锁、条件变量等。 其中,使用信号量来同…...
spring注解驱动开发(二)
17、Bean的生命周期 bean的生命周期:bean的创建—初始化—销毁的过程 容器负责管理bean的生命周期 我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法 构造(对象创建) 单…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
python可视化:俄乌战争时间线关键节点与深层原因
俄乌战争时间线可视化分析:关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一,自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具,系统分析这场战争的时间线、关键节点及其背后的深层原因,全面…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
