Mybatis-Plus(企业实际开发应用)
一、Mybatis-Plus简介
MyBatis-Plus是MyBatis框架的一个增强工具,可以简化持久层代码开发MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官网:MyBatis-Plus
当前版本:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.5.3.2</version>
</dependency>
MyBatis-Plus特性:
• 无侵入:只做增强不做改变,不会对现有工程产生影响
• 强大的 CRUD 操作:内置通用 Mapper,少量配置即可实现单表CRUD 操作
• 支持 Lambda:编写查询条件无需担心字段写错
• 支持主键自动生成
• 内置分页插件
开发方式:
• 单独使用 MyBatis-Plus
• 基于 Spring 使用 MyBatis-Plus
• 基于 SpringBoot 使用 MyBatis-Plus(最常用)
二、CRUD接口
2.1环境搭建
①:创建maven工程,并配置相关基础信息
②:配置pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version><relativePath/></parent><groupId>com.itheima</groupId><artifactId>mp-demo</artifactId><version>0.0.1-SNAPSHOT</version><properties><java.version>11</java.version></properties><dependencies><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
③:配置数据源(application.yml)
#数据源
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mp?useSSL=false&serverTimezone=UTCusername: rootpassword: root
#mybatis-plus
mybatis-plus:mapper-locations: classpath:/mapper/*Mapper.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
⑤:创建实体类与表结构(类名与表名对应,属性名与字段名对应)
可以使用MybatisHelper插件自动生成实体类和Mapper
@TableName(value = "`user`")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {/*** 用户id*/@TableId(value = "id", type = IdType.INPUT)private Long id;/*** 用户名*/@TableField(value = "username")private String username;/*** 密码*/@TableField(value = "`password`")private String password;/*** 注册手机号*/@TableField(value = "phone")private String phone;/*** 详细信息*/@TableField(value = "info")private String info;/*** 使用状态(1正常 2冻结)*/@TableField(value = "`status`")private Integer status;/*** 账户余额*/@TableField(value = "balance")private Integer balance;/*** 创建时间*/@TableField(value = "create_time")private Date createTime;/*** 更新时间*/@TableField(value = "update_time")private Date updateTime;/*** 获取用户id** @return id - 用户id*/public Long getId() {return id;}/*** 设置用户id** @param id 用户id*/public void setId(Long id) {this.id = id;}/*** 获取用户名** @return username - 用户名*/public String getUsername() {return username;}/*** 设置用户名** @param username 用户名*/public void setUsername(String username) {this.username = username;}/*** 获取密码** @return password - 密码*/public String getPassword() {return password;}/*** 设置密码** @param password 密码*/public void setPassword(String password) {this.password = password;}/*** 获取注册手机号** @return phone - 注册手机号*/public String getPhone() {return phone;}/*** 设置注册手机号** @param phone 注册手机号*/public void setPhone(String phone) {this.phone = phone;}/*** 获取详细信息** @return info - 详细信息*/public String getInfo() {return info;}/*** 设置详细信息** @param info 详细信息*/public void setInfo(String info) {this.info = info;}/*** 获取使用状态(1正常 2冻结)** @return status - 使用状态(1正常 2冻结)*/public Integer getStatus() {return status;}/*** 设置使用状态(1正常 2冻结)** @param status 使用状态(1正常 2冻结)*/public void setStatus(Integer status) {this.status = status;}/*** 获取账户余额** @return balance - 账户余额*/public Integer getBalance() {return balance;}/*** 设置账户余额** @param balance 账户余额*/public void setBalance(Integer balance) {this.balance = balance;}/*** 获取创建时间** @return create_time - 创建时间*/public Date getCreateTime() {return createTime;}/*** 设置创建时间** @param createTime 创建时间*/public void setCreateTime(Date createTime) {this.createTime = createTime;}/*** 获取更新时间** @return update_time - 更新时间*/public Date getUpdateTime() {return updateTime;}/*** 设置更新时间** @param updateTime 更新时间*/public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}
}
Mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
2.2 新增操作
新增操作可以调用BaseMapper中提供的insert方法:
/*** 插入一条记录** @param entity 实体对象*/
int insert(T entity);
单元测试方法:
/*** 新增数据*/
@Testpublic void testInsert(){User user = User.builder().username("老八1").password(Base64.getEncoder().encodeToString("123456".getBytes())).phone("18941199302").info("{\"age\": 20, \"intro\": \"青涩老八\", \"gender\": \"female\"}").createTime(Date.from(Instant.now())).updateTime(Date.from(Instant.now())).build();userMapper.insert(user);}
2.3 删除操作
删除操作可以调用BaseMapper中提供的deleteById和deleteBatchIds方法:
/*** 根据 ID 删除** @param id 主键ID*/
int deleteById(Serializable id);
单元测试方法:
/*** 删除数据*/@Testpublic void testDelete(){userMapper.deleteById(7L);}
/*** 删除(根据ID 批量删除)** @param idList 主键ID列表(不能为 null 以及 empty)*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
单元测试方法:
//根据id批量删除数据int batchIds = userMapper.deleteBatchIds(1L,2L,3L);//可变参数System.out.println(batchIds);
2.4 修改操作
/*** 根据 ID 修改** @param entity 实体对象*/
int updateById(@Param(Constants.ENTITY) T entity);
单元测试方法:
/*** 根据Id修改*/@Testpublic void testUpdate(){User user = new User();user.setId(2L);user.setUsername("老六");userMapper.updateById(user);}
2.5 查询操作
/*** 根据 ID 查询** @param id 主键ID*/
T selectById(Serializable id);
单元测试:
/*** 根据Id查找*/@Testpublic void testSelect(){User user = userMapper.selectById(1);System.out.println(user);}
/*** 查询(根据ID 批量查询)** @param idList 主键ID列表(不能为 null 以及 empty)*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
单元测试:
//根据id批量查询数据List<User> users = userMapper.selectBatchIds(Arrays.asList(1625307405933957121L, 1625310776384380930L));System.out.println(users);
/*** 根据 entity 条件,查询全部记录(并翻页)** @param page 分页查询条件(可以为 RowBounds.DEFAULT)* @param queryWrapper 实体对象封装操作类(可以为 null)*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
注意:如果要实现分页功能,需要配置MP框架的分页拦截器:
@Configuration
public class MPConfig {@Beanpublic MybatisPlusInterceptor pageinitInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//乐观锁mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//分页配置mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL) );return mybatisPlusInterceptor;}
}
单元测试:
/*** 分页查询*/@Testpublic void findPage(){IPage<User> page = new Page<>(1,3);userMapper.selectPage(page,null);System.out.println("总页数:" + page.getPages());System.out.println("总记录数:" + page.getTotal());System.out.println("当前页的页码:" + page.getCurrent());System.out.println("每页的数量:" + page.getSize());System.out.println("查到的当前页的内容:" + page.getRecords());}
三、常用注解
3.1 @TableName注解
通过@TableName注解可以映射实体类和表的对应关系。
-
名称:@TableName
-
类型:类注解
-
位置:模型类上
-
作用:设置当前类对应与数据库表关系
-
范例:
@TableName("t_user") //当前实体类对应的表为t_user
public class User {private Long id;
}
注:如果类名和表名一致,MP可以自动进行映射,此时 @TableName 注解可以省略
3.2 @TableField注解
通过@TableField注解可以映射实体类的属性和表字段的对应关系。
-
名称:@TableField
-
类型:属性注解
-
位置:模型类属性上
-
作用:设置当前属性对应的数据库表中的字段关系
-
相关属性:
value:设置数据库表字段名称
exist:设置属性在数据库表字段中是否存在,默认为true
-
范例:
public class User {@TableField(value="pwd") //当前属性对应的字段为pwdprivate String password;@TableField(exist = false) //当前属性在表中没有对应的字段private String online;
}
如果属性名和字段名一致,MP可以自动进行映射,此时 @TableField 注解可以省略
如果属性名使用驼峰命名法命名,字段名使用对应的下划线分隔命名,MP可以自动进行映射,此时 @TableField 注解可以省略。
3.3 @TableId注解
通过@TableId注解可以映射实体类的属性和表主键字段的对应关系,还可以设置主键的生成策略。
-
名称:@TableId
-
类型:属性注解
-
位置:模型类中用于表示主键的属性上
-
作用:映射类中属性和表中主键对应关系,设置主键的生成策略
-
相关属性:
value:设置数据库主键字段名称,如果属性名和字段名一致,可以省略此属性
type:设置主键属性的生成策略,值参照IdType枚举值
-
范例:
public class User {@TableId(type = IdType.AUTO) //当前id属性和表的主键字段id对应,并且设置主键生成策略为AUTOprivate Long id;
}
主键生成策略:
-
AUTO(0):使用数据库id自增策略控制id生成
-
NONE(1):不设置id生成策略
-
INPUT(2):用户手工输入id
-
ASSIGN_ID(3):雪花算法生成id(可兼容数值型与字符串型)
-
ASSIGN_UUID(4):以UUID生成算法作为id生成策略
为了简化开发,可以在application.yml中配置全局的主键生成策略:
mybatis-plus:global-config:db-config:id-type: assign_id #全局设置主键生成策略
注:配置了全局的主键生成策略,在实体类中就无须再配置主键生成策略了。
四、条件构造器
4.1 条件构造器介绍
通过条件构造器(Wrapper),可以控制最终生成的 SQL 语句的条件部分,如下:
-
select_____________ from table where_________ order by
-
update table set________ where_________
-
delete from table where___________
通过条件构造器,就可以控制上面SQL语句中位置的SQL片段,在项目开发过程中经常使用到。
BaseMapper中的很多方法,都需要条件构造器作为参数,如下:
条件构造器的顶级父类为Wrapper:
条件构造器的继承关系如下:
使用比较多的条件构造器:
-
QueryWrapper
-
LambdaQueryWrapper
-
UpdateWrapper
-
LambdaUpdateWrapper
4.2 QueryWrapper
通过 QueryWrapper 条件构造器,可以控制最终生成的查询、删除类的SQL语句。
SQL结构:
-
select ___ from table where ___ order by ___
-
delete from table where ___
/*** 根据条件动态查询*/@Testpublic void selectList(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.select("id","username","password","info") //设置查询字段.like("username","浩") //模糊查询.orderByDesc("id"); //排序条件List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);}
分页查询
/*** 分页查询*/@Testpublic void findPage() {IPage<User> page = new Page<>(1, 3);userMapper.selectPage(page, null);System.out.println("总页数:" + page.getPages());System.out.println("总记录数:" + page.getTotal());System.out.println("当前页的页码:" + page.getCurrent());System.out.println("每页的数量:" + page.getSize());System.out.println("查到的当前页的内容:" + page.getRecords());}
配置分页拦截器
/*** TODO 类描述** @author Aaron.* @date 2023/10/24 11:18*/
@Configuration
public class MPConfig {@Beanpublic MybatisPlusInterceptor pageinitInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//乐观锁mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//分页配置mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL) );return mybatisPlusInterceptor;}
}
4.3 LambdaQueryWrapper
LambdaQueryWrapper的作用和QueryWrapper相同,都是控制最终生成的查询、删除类的SQL语句。不同点在于语法层面。QueryWrapper是通过字段名来设置条件,LambdaQueryWrapper是通过Lambda语法来设置条件,可以做到在编译期就能够发现错误。
@Testpublic void testLambdaQueryByQueryWrapper() {LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>().like(User::getUsername, "o").gt(User::getBalance, 2000);List<User> users = userMapper.selectList(lambdaQueryWrapper);for (User user : users) {System.out.println(user);}}
项目开发中建议使用 LambdaQueryWrapper 来代替 QueryWrapper。
4.4 UpdateWrapper
通过 UpdateWrapper 条件构造器,可以控制最终生成的更新类的SQL语句。
SQL结构:
-
update table set ___ where ___
BaseMapper中的如下方法可以传入UpdateWrapper对象:
//将Id为1、5、7的人员工资扣200@Testpublic void testUpdateWrapper() {UpdateWrapper<User> wrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id", 1L, 5L, 7L);userMapper.update(null, wrapper);}
使用 BaseMapper 的 update 方法设置 set 条件时,既可以通过第一个参数(实体对象)设置,也可以通过第二个参数(UpdateWrapper)设置。
注:使用UpdateWrapper设置条件时,是通过字符串指定字段名,如果字段名有误,在编译阶段无法发现错误,在程序运行阶段会抛出异常。
4.5 LambdaUpdateWrapper
LambdaUpdateWrapper的作用和UpdateWrapper相同,都是控制最终生成的更新类的SQL语句。不同点在于语法层面。UpdateWrapper是通过字段名来设置条件,LambdaUpdateWrapper是通过Lambda语法来设置条件,可以做到在编译期就能够发现错误。
//使用LambdaWrapper进行查询@Testpublic void testSelectWithLambdaWrapper() {//select username,info from user where status = 1 order by balance DescLambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.select(User::getUsername, User::getInfo).eq(User::getStatus, 1).orderByDesc(User::getBalance);userMapper.selectList(wrapper);}
4.6 润物无声
已经使用了MP,还能够使用 mybatis 进行 SQL 定义吗?
注意:MP只是对 mybatis 框架进行增强,不会改变 mybatis 框架的使用方法。也就是说原来怎么使用 mybatis 的,现在还可以按照原来的方式使用即可,如下:
为了进一步增强 mybatis 的功能,我们还可以在 Mapper 中声明方法时,方法的参数使用MP提供的Wrapper条件构造器对象,例如:
上面Mapper中声明的findByCondition方法,参数为 Wrapper类型,即条件构造器对象。并且通过@Param注解修饰,为其指定了别名为ew,这样就可以在SQL语句中通过 ${ew.customSqlSegment} 来获取到对应的SQL片段,这个SQL片段就是通过当前Wrapper对象解析成的。
注意,customSqlSegment为固定写法,底层会调用Wrapper对象的getCustomSqlSegment方法来获取对应的SQL片段。下面是Wrapper类的部分源码:
在单元测试方法中测试findByCondition方法
五、扩展功能
5.1 逻辑删除
删除数据库中的数据,可以通过物理删除,也可以通过逻辑删除。
-
物理删除 指的是直接将数据从数据库中删除,执行的是delete语句
-
逻辑删除 指的是修改数据的某个字段,使其表示为已删除状态,执行的是update语句
如下是逻辑删除的效果,在表中增加deleted字段,标识数据是否被删除(例如:1表示删除,0表示未删除)。
注意:对于重要的、后期可能需要恢复的数据,可以考虑使用逻辑删除
由于在项目开发过程中经常会使用到逻辑删除,所以MP框架已经对逻辑删除提供了实现,我们直接使用即可。
具体使用步骤如下:
第二步:在application.yml中配置逻辑删除相关配置项
logic-delete-field: deleted #指定用于标记数据被删除的字段名logic-delete-value: 1 #表示已删除logic-not-delete-value: 0 #表示未删除
第三步:在实体类中加入逻辑删除属性(和表中的逻辑删除字段对应),并加入 @TableLogic 注解
加入逻辑删除后,再次调用BaseMapper的删除方法和查询方法,发出的SQL语句已经发生了变化。
删除数据时发出的SQL为update语句,将deleted字段的值改为1,表示当前数据被删除了。
查询数据时发出的SQL语句自动追加上查询条件 deleted=0,表示查询的数据是未删除的数据。
5.2 MP对于Service层的支持
MP 框架除了可以简化持久层代码开发,还为 Service 层提供了业务接口和实现类,可以简化 Service 层的开发。
MP提供的业务接口:
MP提供的业务层实现类:
5.3 代码生成器
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装,如下所示:
代码生成器的操作步骤:
① 在IDEA的DataBase窗口中配置数据源
② 通过代码生成器提供的菜单项生成代码
选中表,然后点右键,在弹出的菜单中点击 MybatisX-Generator,此时会弹出如下窗口:
module path:指定代码生成到哪个模块中
base-package:指定代码生成的包结构
ignore table prefix:忽略表名前缀,例如表名为t_user,此时指定当前输入框为t_,则生成的实体类名就是User,否则生成的实体类名为TUser
ignore field prefix:忽略字段名前缀,例如字段名为f_name,此时指定当前输入框为f_,则生成的属性名就是name,否则生成的属性名为fName
通过代码生成器,就可以根据表结构,反向生成对应的实体类、Mapper、Service等,可以简化开发,提供开发效率。
相关文章:

Mybatis-Plus(企业实际开发应用)
一、Mybatis-Plus简介 MyBatis-Plus是MyBatis框架的一个增强工具,可以简化持久层代码开发MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 官网&a…...

Spring Web MVC入门
一:了解Spring Web MVC (1)关于Java开发 🌟Java开发大多数场景是业务开发 比如说京东的业务就是电商卖货、今日头条的业务就推送新闻;快手的业务就是短视频推荐 (2)Spring Web MVC的简单理解 💗Spring Web MVC:如何使…...

【C++】mapset的底层结构 -- AVL树(高度平衡二叉搜索树)
前面我们对 map / multimap / set / multiset 进行了简单的介绍,可以发现,这几个容器有个共同点是:其底层都是按照二叉搜索树来实现的。 但是二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者接近有序,二叉搜索…...

吴恩达《机器学习》1-4:无监督学习
一、无监督学习 无监督学习就像你拿到一堆未分类的东西,没有标签告诉你它们是什么,然后你的任务是自己找出它们之间的关系或者分成不同的组,而不依赖于任何人给你关于这些东西的指导。 以聚类为例,无监督学习算法可以将数据点分成…...

一个简单的注册页面,如有错误请指正(2.css)
这段CSS代码定义了页面的样式,让我逐个解释其功能: 1. * {}:通配符选择器,用于将页面中的所有元素设置统一的样式。这里将margins和paddings设置为0,以去除默认的边距。 2. div img {}:选择页面中所有div…...

【Unity精华一记】特殊文件夹
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:uni…...

Node.js中的单线程服务器
为了解决多线程服务器在高并发的I/O密集型应用中的不足,同时避免早期简单单线程服务器的性能障碍,Node.js采用了基于"事件循环"的非阻塞式单线程模型,实现了如下两个目标: (1)保证每个请求都可以…...

如何删除数组中的某个元素?
如何删除数组中的某个元素? 例:给你一个数组 nums 和一个值 val,你需要移除所有数值等于 val 的元素,并返回移除后数组的新长度。 三种方法 1.元素前移(时间复杂度:O(N^2),空间复杂度&#x…...

Apache ActiveMQ RCE漏洞复现(CNVD-2023-69477)
0x01 产品简介 ActiveMQ是一个开源的消息代理和集成模式服务器,它支持Java消息服务(JMS) API。它是Apache Software Foundation下的一个项目,用于实现消息中间件,帮助不同的应用程序或系统之间进行通信。 0x02 漏洞概述 Apache ActiveMQ 中存…...

【BUG】Nginx转发失败解决方案
最近在做项目的时候出现了一个问题,琢磨了好久,来浅浅记录一下。 这个项目后端使用的是gateway网关和nacos实现动态的路由,前端使用nginx来管理前端资源,大体流程:浏览器发起请求,经过nginx代理,…...

综合OA管理系统源码 OA系统源码
综合OA管理系统源码 OA系统源码 功能介绍: 编号:LQ10 一:系统管理 系统配置,功能模块,功能节点,权限角色,操作日志,备份数据,还原数据 二:基础数据 审批…...

9-MySQL提高数据管理效率(分库分表实践)
MySQL提高数据管理效率(分库分表实践) 在当今的互联网时代,随着业务规模的不断扩大,数据量也呈现出爆炸性的增长。如何有效地管理和存储这些数据,以及提高数据库的性能和可扩展性,成为了一个迫切需要解决的…...

经典卷积神经网络 - NIN
网络中的网络,NIN。 AlexNet和VGG都是先由卷积层构成的模块充分抽取空间特征,再由全连接层构成的模块来输出分类结果。但是其中的全连接层的参数量过于巨大,因此NiN提出用1*1卷积代替全连接层,串联多个由卷积层和“全连接”层构成…...

leetcode_2558 从数量最多的堆取走礼物
1. 题意 给定一个数组,每次从中取走最大的数,返回开根号向下取整送入堆中,最后计算总和。 从数量最多的堆取走礼物 2. 题解 直接用堆模拟即可 2.1 我的代码 用了额外的空间O( n ) priority_queue会自动调用make_heap() 、pop_heap() c…...

01. 嵌入式与人工智能是如何结合的?
CPU是Arm A57的 GPU是128cuda核 一.小车跟踪的需求和设计方法 比如有一个小车跟踪的项目。 需求是:小车识别出罪犯,然后去跟踪他。方法:摄像头采集到人之后传入到开发板,内部做一下识别,然后控制小车去跟随。在人工智…...

vue3.0运行npm run dev 报错Cannot find module node:url
vue3.0运行npm run dev 报错Cannot find module 问题背景 近期用vue3.0写项目,npm init vuelatest —> npm install 都正常,npm run dev的时候报错如下: failed to load config from F:\code\testVue\vue-demo\vite.config.js error when starting…...

26. 删除排序数组中的重复项、Leetcode的Python实现
博客主页:🏆看看是李XX还是李歘歘 🏆 🌺每天分享一些包括但不限于计算机基础、算法等相关的知识点🌺 💗点关注不迷路,总有一些📖知识点📖是你想要的💗 ⛽️今…...

荣耀推送服务消息分类标准
前言 为了提升终端用户的推送体验、营造良好可持续的通知生态,荣耀推送服务将对推送消息进行分类管理。 消息分类 定义 荣耀推送服务将根据应用类型、消息内容和消息发送场景,将推送消息分成服务通讯和资讯营销两大类别。 服务通讯类,包…...

[数据结构]-二叉搜索树
前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 一、二叉搜…...

力扣每日一题79:单词搜索
题目描述: 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格…...

ChatGPT如何应对用户提出的道德伦理困境?
ChatGPT在应对用户提出的道德伦理困境时,需要考虑众多复杂的因素。道德伦理问题涉及到价值观、原则、社会和文化背景,以及众多伦理理论。ChatGPT的设计和应用需要权衡各种考虑因素,以确保它不仅提供有用的信息,而且遵循伦理标准。…...

SpringBoot运行流程源码分析------阶段三(Spring Boot外化配置源码解析)
Spring Boot外化配置源码解析 外化配置简介 Spring Boot设计了非常特殊的加载指定属性文件(PropertySouce)的顺序,允许属性值合理的覆盖,属性值会以下面的优先级进行配置。home目录下的Devtool全局设置属性(~/.sprin…...

环形链表-力扣
一、题目描述 题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 二、题解 解题思路: 快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,…...

人生岁月年华
人生很长吗?不知道。只知道高中坐在教室里,闹哄哄的很难受。也记得上班时无聊敲着代码也很难受。 可是人生也不长。你没有太多时间去试错,你没有无限的时间精力去追寻你认为的高大上。 人生是何体验呢?人生的感觉很多吧。大多数…...

电脑QQ如何录制视频文件?
听说QQ可以录制视频,还很方便,请问该如何录制呢?是需要先打开QQ才可以录制吗?还是可以直接使用快捷键进行录制呢?录制的质量又如何呢? 不要着急,既然都打开这篇文章看了,那小编今天…...

python:多波段遥感影像分离成单波段影像
作者:CSDN @ _养乐多_ 在遥感图像处理中,我们经常需要将多波段遥感影像拆分成多个单波段图像,以便进行各种分析和后续处理。本篇博客将介绍一个用Python编写的程序,该程序可以读取多波段遥感影像,将其拆分为单波段图像,并保存为单独的文件。本程序使用GDAL库来处理遥感影…...

天堂2游戏出错如何解决
运行游戏时出现以下提示:“the game may not be consistant because AGP is deactivated please activate AGP for consistancy” 这个问题的原因可能是由于您的显示卡的驱动或者主板的显示芯片组的驱动不是新开。或您虽然已经更新了您的显示卡的驱动程序࿰…...

『力扣刷题本』:合并两个有序链表(递归解法)
一、题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入:l1 [], l2 [] 输出&#x…...

C++设计模式_12_Singleton 单件模式
在之前的博文C57个入门知识点_44:单例的实现与理解中,已经详细介绍了单例模式,并且根据其中内容,单例模式已经可以在日常编码中被使用,本文将会再做梳理。 Singleton 单件模式可以说是最简单的设计模式,但由…...

67 内网安全-域横向smbwmi明文或hash传递
#知识点1: windows2012以上版本默认关闭wdigest,攻击者无法从内存中获取明文密码windows2012以下版本如安装KB2871997补丁,同样也会导致无法获取明文密码针对以上情况,我们提供了4种方式解决此类问题 1.利用哈希hash传递(pth,ptk等…...