MyBatis-Plus的入门学习
MyBatis-Plus入门学习
- 简介
- 特性
- 快速开始
- MyBatis-Plus的注解详解
- @Tableld
- 主键生成策略
- 1、数据库自动增长 AUTO
- 2、UUID
- 3、Redis生成id
- 4、MP主键自动生成
- @TableName
- @TableField
- 自动填充
- 测试方法:
- update
- 乐观锁
- select
- 查所有
- 根据id查
- 多个id批量查询
- 简单条件查询(通过map封装条件)
- 分页
- delete
- 根据id删除
- 批量删除
- 简单的条件查询删除
- 逻辑删除
- 性能分析
- Wrapper
- wrapper条件构造器测试
- 1、ge、gt、le、lt、isNull、isNotNull
- 2、eq、ne
- 3、between、notBetween
- 4、allEq
- 5、like、notLike、likeLeft、likeRight
- 6、in、notIn、inSql、notInSql、exists、notExists
- 7、or、and
- 8、嵌套or、嵌套and
- 9、orderBy、orderByDesc、orderByAsc
- 10、last
- 11、set、setSql
简介
MyBatis-Plus是MyBatis的增强工具,在MyBatis的基础上做出增强改变,简化开发,提高效率
mybatis-plus的官网链接
特性
快速开始
第一步:创建一张表
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)
);
第二步:插入对应数据
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');
第三步:初始化一个项目工程
第四步:引入依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0+ 版本</version><relativePath/>
</parent><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><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>最新版本</version></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency>
</dependencies>
第五步:配置数据库连接信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?
serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
第五步:在SpringBoot项目的启动类中添加**@MapperScan注解**,用于对mapper的扫描
package com.example.mpdemo001;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.example.mpdemo001.mapper")
public class Mpdemo001Application {public static void main(String[] args) {SpringApplication.run(Mpdemo001Application.class, args);}}
第六步:编码
实体类:
package com.example.mpdemo001.bean;import lombok.Data;/*** @Title: User* @Package com.example.mpdemo001.bean* @Author: CXY* @Copyright CXY* @CreateTime: 2023/3/9 12:35*/
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}
mapper接口(MyBatis-Plus不需要在接口中写很多方法,只需要继承 BaseMapper< T>即可,T表示泛型)
package com.example.mpdemo001.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mpdemo001.bean.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {
}
**注意:**在mapper接口上面需要添加一个@Mapper的注解,用于将Mapper接口加入Spring管理
第七步:测试
package com.example.mpdemo001;import com.example.mpdemo001.bean.User;
import com.example.mpdemo001.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
public class Mpdemo001ApplicationTests {@Autowiredprivate UserMapper userMapper;@Testpublic void contextLoads() {List<User> users = userMapper.selectList(null);for (User user:users) {System.out.println(user);}}}
UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件
测试结果:
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)
可以配置MyBatis-Plus的日志文件,这样可以看到详细的SQL语句实现过程
日志文件的配置如下:
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
MyBatis-Plus的注解详解
@Tableld
IdType:顾名思义即表示主键的类型
主键生成策略
参考资料:分布式系统唯一ID生成方案汇总:https://www.cnblogs.com/haoxinyue/p/5208136.htm
1、数据库自动增长 AUTO
这个是指在建表的时候可以直接设置id自增,这样的话idType即为AUTO;
**缺点:**这样id自增的主键,不利于数据库的分表实现,因为id是按顺序递增的,所以每一次分表的时候都需要知道前一张表的最后一个id的值,再那个基础上进行id加一的操作
2、UUID
每次生成随机唯一的值
**优点:**每次分表的时候不需要知道上一张表的最后一个元素的id值
**缺点:**id无法进行排序
3、Redis生成id
Redis是单线程的,所以也可以用来生成全局唯一的id,可以用Redis的原子操作INCR和INCRBY来实现
但是使用这个来进行id生成的时候,需要指定初始值和步长
使用Redis集群可以防止单点故障的问题
单点故障:(英语:single point of failure,缩写SPOF)是指系统中一点失效,就会让整个系统无法运作的部件,换句话说,单点故障即会整体故障。
**优点:**不依赖于数据库,灵活方便,且性能优于数据库,数字id天然排序,对分页或者需要排序的结果很有帮助
**缺点:**如果系统中没有Redis,还需引入新的主键,增加系统的复杂度;需要编码和配置的工作量比较大
4、MP主键自动生成
mp可以通过雪花算法自动生成一个19位数字的id,
@TableName
- 描述:表名注解,标识实体类对应的表
- 使用位置:实体类
@TableField
- 描述:字段注解(非主键)
自动填充
将数据自动填充进去
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。 我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作
具体实现过程:
在实体类中需要自动进行自动填充的对象上面添加注解:**@TableField(fill=FieldFill.Xxx)**FieldFill的取值:
然后创建一个类用于实现MetaObjectHandler接口,实现接口中的方法,
注意:需要在这个类上面添加注解,让Spring进行管理
package com.example.mpdemo001.bean;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;import java.util.Date;/*** @Title: MyBatisMeta* @Package com.example.mpdemo001.bean* @Author: CXY* @Copyright CXY* @CreateTime: 2023/3/10 14:02*/
@Component
//这个不能忘,忘了就无法进行了
public class MyBatisMeta implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {//插入时间,第一次创建的时候,需要插入创建时间和更新时间this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {//每一次更新数据的时候,插入时间this.setFieldValByName("updateTime",new Date(),metaObject);}
}
测试结果:
测试方法:
update
@Test
public void testUpdateById(){User user=new User();user.setId(1L);user.setName("战三");int i = userMapper.updateById(user);System.out.println(i);}
结果:
注意:update生成的是动态sql
乐观锁
针对一种特定问题的解决方案,主要解决的是丢失更新的问题
主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数 据更新
如果不考虑事务的隔离性的话,会产生的问题有:
1、产生读问题:脏读,不可重复读,幻读
2、产生写问题:丢失更新(就是指多个人同时修改同一条数据,最后提交的把之前提交的数据覆盖了)
解决丢失更新问题:
悲观锁:串行,只有一个人能在当前情况下进行操作
乐观锁:添加了一个version版本号,当一个人在进行数据操作的时候,提交数据时会比较当前数据版本号和数据库中的版本号是否一直,如果一致则可以进行修改,修改后版本号进行加一的操作。反之不能进行修改。
**乐观锁的使用例子有:**12306抢票系统,当别人把最后一张票抢走之后,另外的人就不能再进行抢票了
乐观锁的使用流程:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
当有很多配置的时候,建议新建一个配置类,将所有配置写在配置类中
package com.example.mpdemo001.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Title: MyBatisConfigurations* @Package com.example.mpdemo001.config* @Author: CXY* @Copyright CXY* @CreateTime: 2023/3/10 15:12*/
@Configuration
@MapperScan("com.example.mpdemo001.mapper")
public class MyBatisConfigurations {/*** 乐观锁插件** 新版*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}}
测试成功代码:
@Test
public void testOptimisticLockerFail() {User user = userMapper.selectById(1l);user.setName("死亡法师");user.setAge(10000);int i = userMapper.updateById(user);System.out.println(i);
}
测试成功的结果
测试失败代码:
@Test
public void testOptimisticLockerFail() {User user = userMapper.selectById(2l);user.setName("哈利波特");user.setAge(300);//模拟取出数据后,数据库中version实际数据比取出的值大,即已被其它线程修改并更新了versionuser.setVersion(user.getVersion()-1);int i = userMapper.updateById(user);System.out.println(i);
}
结果:
select
查所有
@Test
public void testSelect(){List<User> users = userMapper.selectList(null);users.forEach(System.out::println);
}
结果
根据id查
多个id批量查询
简单条件查询(通过map封装条件)
注意:map中的key对应的是数据库中的列名。例如数据库user_id,实体类是userId,这时map的key需 要填写user_id
分页
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
添加插件:
/*** 分页插件(官网最新)*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor1() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;
}
测试分页实现:
@Test
public void testPageSelect(){Page page=new Page<>(1,3);userMapper.selectPage(page, null);page.getRecords().forEach(System.out::println);System.out.println(page.getCurrent());System.out.println(page.getPages());System.out.println(page.getSize());System.out.println(page.getTotal());System.out.println(page.getRecords());}
测试结果
分页的各个属性:
delete
根据id删除
@Test
public void testDeletedById(){int i = userMapper.deleteById(4l);System.out.println(i);
}
批量删除
@Test
public void testDeletedByIds(){int i = userMapper.deleteBatchIds(Arrays.asList(1, 2, 3));System.out.println(i);
}
简单的条件查询删除
@Test
public void testDeleteByMap(){HashMap<String,Object> hashMap=new HashMap<>();hashMap.put("name","Tom");hashMap.put("age",28);int i = userMapper.deleteByMap(hashMap);System.out.println(i);
}
逻辑删除
逻辑删除就是指在数据中多加一个标志属性,删除的时候只对该属性进行修改,而不是真正的删除数据,逻辑删除有利于数据的恢复
- 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
- 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍 旧能看到此条数据记录
在实体类上添加deleted属性
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;
如果想修改默认属性值,则可在application.properties中进行配置
默认0表示未被删除,1表示被删除
在配置类中注册bean
@Bean
public ISqlInjector sqlInjector() {return new LogicSqlInjector();
}
高版本不用配置插件了,上述java代码无需编写。
测试删除:
@Test
public void testLogicDelete() {int result = userMapper.deleteById(1L);System.out.println(result);
}
被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操做
性能分析
在配置类中添加性能优化插件
@Profile({“dev”,“test”})表示对什么环境起作用
dev:开发环境
test:测试环境
prod:生产环境,项目部署好之后的环境 最好不要在这里使用性能优化插件
环境配置在配置文件中设置:
spring.profile.active=xxx(dev,test,prod)
**参数:**maxTime: SQL 执行最大时长,超过自动停止运行,有助于发现问题。
**参数:**format: SQL是否格式化,默认false
Wrapper
- Wrapper : 条件构造抽象类,最顶端父类
- AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
- QueryWrapper : Entity 对象封装操作类,不是用lambda语法(使用较多)
- UpdateWrapper : Update 条件封装,用于Entity对象更新操作
- AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
- LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
- LambdaUpdateWrapper : Lambda 更新封装Wrapper
wrapper条件构造器测试
1、ge、gt、le、lt、isNull、isNotNull
@Test
public void testQueryWrapper(){QueryWrapper<User> queryWrapper=new QueryWrapper<>();queryWrapper.isNull("email").ge("age",30).isNotNull("name");//上面代码可以表示多个条件int delete = userMapper.delete(queryWrapper);System.out.println(delete);
}
gt:大于;ge:大于等于;le:小于;lt:小于等于
2、eq、ne
eq表示等于
ne表示不等于
@Test
public void testSelectOne() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("name", "Tom");User user = userMapper.selectOne(queryWrapper);System.out.println(user);
}
注意:selectOne方法返回的是一条实体记录,如果返回多条时,会报错
3、between、notBetween
是包含边界值的查询条件
需要注意小值在前,大值在后
@Test
public void testSelectCount() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.between("age", 20, 30);Long count = userMapper.selectCount(queryWrapper);System.out.println("==============="+count);
}
4、allEq
多条件均相等
@Test
public void testSelectList() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();Map<String, Object> map = new HashMap<>();map.put("id", 2);map.put("name", "Jack");map.put("age", 20);queryWrapper.allEq(map);List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
5、like、notLike、likeLeft、likeRight
like:模糊查询,表示like %内容%
notLike:不包含
likeLeft:表示like %内容
likeRight:表示 like 内容%
@Test
public void testQuerrySelectMaps() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.notLike("name","san").likeRight("email","test1");List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);maps.forEach(System.out::println);}
6、in、notIn、inSql、notInSql、exists、notExists
in notIn用法如下:
notIn(“age”,{1,2,3})—>age not in (1,2,3)
notIn(“age”, 1, 2, 3)—>age not in (1,2,3)
inSql、notInSql可以实现子查询
@Testpublic void testSelectObjs() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//queryWrapper.in("id", 1, 2, 3);queryWrapper.inSql("id", "select id from user where id < 3");List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表objects.forEach(System.out::println);}
7、or、and
不调用or则默认为使用 and 连
8、嵌套or、嵌套and
这里使用了lambda表达式,or中的表达式最后翻译成sql时会被加上圆括号
@Testpublic void testUpdate2() {
//修改值User user = new User();user.setAge(99);user.setName("Andy");
//修改条件UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();userUpdateWrapper.like("name", "h").or(i -> i.eq("name", "李白").ne("age", 20));
// i -> i.eq("name", "李白").ne("age", 20)这一段是lambda表达式int result = userMapper.update(user, userUpdateWrapper);System.out.println(result);}
最后的sql语句为:
UPDATE user SET name=?, age=?, update_time=? WHERE deleted=0 AND name LIKE ?
OR ( name = ? AND age <> ?)
9、orderBy、orderByDesc、orderByAsc
**orderBy:**默认是升序
**orderByDesc:**表示升序排列,该方法可以有多个条件参与排列
**orderByAsc:**表示降序排列,该方法可以有多个条件参与排列
10、last
直接拼接到 sql 的最后
注意:只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
@Test
public void testSelectListLast() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.last("limit 1");List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
sql语句:SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 limit 1
11、set、setSql
最终的sql会合并 user.setAge(),以及 userUpdateWrapper.set() 和 setSql() 中 的字段
@Testpublic void testUpdateSet() {
//修改值User user = new User();user.setAge(99);
//修改条件UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();userUpdateWrapper.like("name", "h").set("name", "老李头")//除了可以查询还可以使用set设置修改的字段.setSql(" email = '123@qq.com'");//可以有子查询int result = userMapper.update(user, userUpdateWrapper);}
sql语句:
UPDATE user SET age=?, update_time=?, name=?, email = ‘123@qq.com’ WHERE deleted=0 AND name LIKE ?
b站教学视频:
尚硅谷
相关文章:
MyBatis-Plus的入门学习
MyBatis-Plus入门学习简介特性快速开始MyBatis-Plus的注解详解Tableld主键生成策略1、数据库自动增长 AUTO2、UUID3、Redis生成id4、MP主键自动生成TableNameTableField自动填充测试方法:update乐观锁select查所有根据id查多个id批量查询简单条件查询(通…...
华为OD机试题 - 内存池(JavaScript)
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:内存池题目输入输出示例一输入输出说明Code解题思路版权说明华为…...
数据库索引原理
数据库索引的作用是做数据的快速检索,而快速检索实现的本质是数据结构。像二叉树、红黑树、AVL树、B树、B树、哈希等数据结构都可以实现索引,但其中B树效率最高。MySQL数据库索引使用的是B树。二叉树:二叉树中,左子树比根节点小&a…...
字符函数和字符串函数详解(1)
目录前言strlen函数strlensizeofstrcpy函数strcat函数strcmp函数总结前言 最近要调整状态,写的文章质量不佳让大家失望,我现在也在反思我在做什么,我会什么,我学了什么。等我想明白的那天,我一定能跟大家顶峰相见的&a…...
【数据分析:工具篇】NumPy(1)NumPy介绍
【数据分析:工具篇】NumPy(1)NumPy介绍NumPy介绍NumPy的特点数组的基本操作创建数组索引和切片数组运算NumPy介绍 NumPy(Numerical Python)是Python的一个开源的科学计算库,它主要用于处理大规模的多维数组…...
mysql时区问题
设置mysql容器时间与服务器时间一致 问题背景: 今天测试发现一个问题,时间不一致,当工单入库时,其创建时间和更新时间应该是一样的,即使不一样最多只会错几秒的时间;实际上两个时间相差的大概8小时&#…...
磨金石教育摄影技能干货分享|高邮湖上观花海
江苏高邮,说到这里所有人能想到的,就是那烟波浩渺的高邮湖。高邮在旅游方面并不出名,但是这里的自然人文景观绝对不输于其他地方。高邮不止有浩瀚的湖泊,春天的油菜花海同样壮观。春日的午后,与家人相约游玩࿰…...
mysql navicat忘记密码
mysql忘记密码是常用的事情,那么如何解决它呢?1、首先将MySQL的服务关闭,两种方法:(1)打开命令行cmd输入net stop mysql命令即可关闭MySQL服务。(2)打开任务管理器,找到服…...
Git的下载、安装、配置、使用、卸载
前言 我是跟着狂神老师学的。该博客仅用于笔记所用。 下面是老师的B站和笔记 B站:https://www.bilibili.com/video/BV1FE411P7B3?p1&vd_source9266cf72b1f398b63abe0aefe358d7d6 笔记:https://mp.weixin.qq.com/s/Bf7uVhGiu47uOELjmC5uXQ 一、准备工…...
【博客631】监控网卡与进程网络IO使用情况
监控进程的网络IO使用情况 1、vnstat 由于 vnstat 依赖于内核提供的信息,因此执行以下命令来验证内核是否提供了 vnStat 所期望的所有信息: # vnstat --testkernel This test will take about 60 seconds. Everything is ok.不带任何参数的 vnstat 将…...
【Leetcode】【简单】35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2 示例 2: 输入:…...
sql面试题
mysql优化 优化准则: 建表时:合理选择字段的类型,单表字段数量 sql查询尽量单表操作,避免复杂操作,复杂的多表通过java代码实现 构建复合索引优化,索引尽量可以覆盖主要业务查询 sql避免索引失效 避免大…...
SQL 进阶刷题笔记
SQL 进阶刷题笔记 一、MySQL 进阶 这里主要是 MySQL 刷题相关笔记,方便后面温习和查阅,希望可以帮到大家!!! 题1 请计算每张SQL类别试卷发布后,当天5级以上的用户作答的人数uv和平均分avg_score࿰…...
[网鼎杯 2020 朱雀组]Think Java
SqlDict.java ,其中sql语句处存在sql注入漏洞 package .sqldict;import cn.abc.core.sqldict.Row; import cn.abc.core.sqldict.Table; import java...
AIR32F103(十) 在无系统环境和FreeRTOS环境集成LVGL
目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告AIR32F103(二) Linux环境和LibOpenCM3项目模板AIR32F103(三) Linux环境基于标准外设库的项目模板AIR32F103(四) 27倍频216MHz,CoreMark跑分测试AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码AIR32F103(六) ADC,I2S…...
SpringBoot接口 - 如何统一异常处理
SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?为什么要优雅的处理异常如果我们不统一的处理异常,经常会在controller层有大量的异常…...
如何使用Python进行数据可视化
数据可视化是一种将数据呈现为图形或图表的技术,它有助于理解和发现数据中的模式和趋势。Python是一种流行的编程语言,有很多库可以帮助我们进行数据可视化。在本文中,我们将介绍使用Python进行数据可视化的基本步骤。 第一步:导…...
vue -- 自定义指令钩子函数补充 自定义过滤器filter参数
自定义指令补充 自定义指令通过钩子函数的形式来实现自定义的功能 这里是几个常用的钩子函数以及它的方法: bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。 inserted:被绑定元素插…...
Qt不会操作?Qt原理不知道? | Qt详细讲解
文章目录Qt界面开发必备知识UI界面与控件类型介绍Qt设计器原理控件类型的介绍信号与槽机制处理常用控件创建与设置常见展示型控件创建与设置常见动作型控件创建与设置常见输入型控件创建与设置常见列表控件创建于设置Qt中对象树的介绍项目源码结构刨析.pro.hmain.cpp.cppQt界面…...
LeetCode-面试题 17.05. 字母与数字【前缀和,哈希表】
LeetCode-面试题 17.05. 字母与数字【前缀和,哈希表】题目描述:解题思路一:前缀和。数字为-1,字母为1。我们需要找到的子数组是前缀和之差为0的,例如s[right]-s[left]0,那么s[right]s[left],变为…...
华为OD机试题 - 叠放书籍(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:叠放书籍题目输入输出示例一输入输出Code解题思路版权说明华为O…...
【数据库概论】第十一章 数据库并发控制
第十一章 并发控制 在多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现多个事务并行运行,这就是同时并发方式。当多个用户并发存取数据库时会产生多个事务同时存取同一事务的情况,如果…...
Nginx配置实例-反向代理案例二
实现效果:使用nginx反向代理,根据访问的路径跳转到不同端口服务 nginx监听端口为9000, 访问 http://127.0.0.1:9000/edu/ 直接跳转到127.0.0.1:8080 访问 http://127.0.0.1:9000/vod/ 直接跳转到127.0.0.1:8081 一、准备工作 1. 准备两个tom…...
HTML 字符集
为了正确显示 HTML 页面,Web 浏览器必须知道要使用哪个字符集。 从 ASCII 到 UTF-8 ASCII 是第一个字符编码标准。ASCII 定义了 128 种可以在互联网上使用的字符:数字(0-9)、英文字母(A-Z)和一些特殊字符…...
【C语言】每日刷题 —— 牛客语法篇(3)
前言 大家好,继续更新专栏c_牛客,不出意外的话每天更新十道题,难度也是从易到难,自己复习的同时也希望能帮助到大家,题目答案会根据我所学到的知识提供最优解。 🏡个人主页:悲伤的猪大肠9的博客…...
基于Vue3和element-plus实现一个完整的登录功能
先看一下最终要实现的效果:登录页面:注册页面:(1)引入element-plus组件库引入组件库的方式有好多种,在这里我就在main.js全局引入了.npm i element-plus -Smain.js中代码:import { createApp } from "vue"; //element-plus import ElementPlus from "element-pl…...
【java】Java 中泛型的实现原理
文章目录前序1. 泛型1.1 泛型方法1.2 泛型类1.3 泛型接口2. 泛型的基本原理3. 小结前序 泛型是 Java 开发中常用的技术,了解泛型的几种形式和实现泛型的基本原理,有助于写出更优质的代码。本文总结了 Java 泛型的三种形式以及泛型实现原理。 1. 泛型 …...
【C++提高编程】C++全栈体系(二十七)
C提高编程 第五章 STL- 常用算法 三、常用排序算法 算法简介: sort //对容器内元素进行排序random_shuffle //洗牌 指定范围内的元素随机调整次序merge // 容器元素合并,并存储到另一容器中reverse // 反转指定范围的元素 1. sort 功能描述&#…...
软考高级信息系统项目管理师系列之三十九:项目集管理
软考高级信息系统项目管理师系列之三十九:项目集管理 一、项目集管理内容二、项目集管理基础概述1.项目集定义2.项目集活动3.项目集管理三、项目集的管理过程四、项目集治理1.项目集治理概述2.项目集指导委员会的职责3.项目集治理功能五、项目集生命周期1.项目集生命周期三个阶…...
44-Golang中的channel
Golang中的channel为什么要使用channelchannel的介绍channel的基本使用定义/声明channel管道的遍历和关闭channel的关闭channel的遍历goroutine和channel结合应用实例1应用实例2案例注意事项为什么要使用channel 前面使用全局变量加锁同步来解决goroutine的通讯,但…...
外贸企业网站建设/搜索引擎seo关键词优化方法
我所举的这个例子是一个企业用户注册时的一个应用,当用户注册时检查用户名和企业名是否可用,以前的做法是在旁边加一个按钮,点击“检查”,就向服务器发出请求,然后等待……服务器返回信息,继续操作。 如…...
网站互动方式/宁波网站推广专业服务
**前言**2006年起,我已经以某种方式进行Web应用开发。我开始为挪威最大的零售商开发Web应用,先是使用JavaServer Pages(JSP)技术,之后换成JavaServer Faces(JSF)。当时这些技术很不错࿰…...
深圳全国网站制作哪个好/网站制作步骤流程图
前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。初学者:《Java练习题》习题集一 https://www.cnblogs.com/jssj/p/11147566.html《Java练习题》习题集二 https://www.cnblog…...
完整php网站开发/抚顺优化seo
房屋详情模块 业务:根据房源 id,展示房源详情信息 3.1 功能分析 功能: 使用路由参数获取房源 id 根据房源 id 获取房源详情数据并展示 使用地图展示所在小区位置信息 房源收藏(需要登录) 重点: 路由参数。 3. 房屋详情模块 3.2 页面模板说明 1. 创建房屋…...
服务器网站建设教程视频教程/网络营销的发展现状及趋势
单元测试是代码正确性验证的最重要的工具,也是系统测试当中最重要的环节。也是唯一需要编写代码才能进行测试的一种测试方法。在标准的开发过程中,单元测试的代码与实际程序的代码具有同等的重要性。每一个单元测试,都是用来定向测试其所对应…...
重庆合川企业网站建设联系电话/天天外链官网
添加的时候通过模糊添加,可能有多个匹配. 删除只能针对编号删除,不能针对某个进行删除. 如果要删除只能重新创建,更精确的匹配. 对具体的某些断点进行禁用启用. 可以通过n.m的方式进行操作,也可以通过n.x-y的方式对多个进行操作....