当前位置: 首页 > news >正文

黑马微服务开发与实战学习笔记_MybatisPlus_P2核心功能

系列博客目录


文章目录

  • 系列博客目录
  • Part1:条件构造器
    • 案例 基于QueryWrapper的查询
    • 案例 基于UpdateWrapper的查询
    • 条件构造器的用法总结
  • Part2:自定义SQL
    • 案例1
    • 案例2
    • 解决方案
  • Part3:IService接口
    • IService接口基本用法
    • 实战案例
      • 准备工作
      • 开始基本用法实战
      • IService的Lambda查询实战
    • 批量新增


Part1:条件构造器

之前的不足:之前的入门案例中,为了简化学习,演示的增删改查都是根据ID进行的,但是真是业务开发中,增删改查的条件很复杂,MP提供条件构造器,帮助我们构建条件。

MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求。下面给出的方法,也是来着BaseMapper,但是他不再用Id当作参数了,而是Wrapper类型的参数,Wrapper就是条件构造器,就是用来构建复杂Sql语句的。
在这里插入图片描述
Wrapper是最顶级的父类,还有很多继承它的。
在这里插入图片描述
比如上图中第二层的AbstractWrapper,从下图可以看出,Sql语句中where条件中写过的条件的很多在这里都有对应的方法,比如eq就是"="
在这里插入图片描述
从上上图可以看到,AbstractWrapper还有几个儿子,也就是进行了继承以及拓展。QueryWrapper就是拓展了查询相关功能,比如查询时候加了条件,指定select哪些字段(如下图所示)。UpdateWrapper就是拓展了更新的相关功能。在这里插入图片描述
从上上上图中左下角可以看到,有三个类,只比之前讲过的三个多了Lambda,和之前的区别就是构建条件的时候,使用了Lambda的语法。

案例 基于QueryWrapper的查询

需求:

  1. 查询出名字中带o的,存款大于等于1000元的人的id、username、info、balance字段。
SELECT id,username,info,balance
FROM user
WHERE username LIKE ? AND balance >= ?

在这里插入图片描述
我们可以通过代码自动补全中给我们的信息来知道,哪个函数使用了Wrapper,哪个函数返回什么类型,通过这两点来确定我们使用哪个函数。

@Test
void testQueryWrapper(){//构建查询条件,实现不通过Id查询QueryWrapper<User> wrapper = new QueryWrapper<User>().select("id","username","info","balance").like("username","o").ge("balance",1000);//实现查询List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);
}

运行结果:
在这里插入图片描述

  1. 更新用户名为iack的用户的余额为2000
UPDATE user
SET balance = 2000 WHERE (username = 'jack")
@Test
void testUpdateByQueryWrapper(){//要更新的数据User user =new User();user.setBalance(2000);//更新的条件QueryWrapper<User>wrapper = new QueryWrapper<User>().eq("username" ,"jack");//执行更新userMapper.update(user, wrapper);
}

在这里插入图片描述

案例 基于UpdateWrapper的查询

需求:更新id为1,2,4的用户的余额,扣200。这种更新比较特殊。每个用户扣完之后金额不同,不能像之前一样直接写死。

UPDATE userSET balance = balance - 200 WHERE id in (124)
@Test
void testUpdateWrapper(){List<Long> ids = List.of(1L,2L,4L);UpdateWrapper<User> wrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id", ids);userMapper.update(null, wrapper); //更新的内容不需要填了,直接在Wrapper中写
}

MP中除了新增,删改查都可以通过Wrapper进行操作。
LambdaWrapper 与 一般Wrapper的区别,是在构造条件时候需要使用Lambda表达式,因为目前我们都是硬编码,字段名都是写死的(比如select("id","username","info","balance")),使用lambda表达式可以解决这个问题。
示例:结果与之前一样,推荐使用Lambda表达式,避免硬编码

void testLambdaQueryWrapper() {// 构建查询条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().select(User::getId, User::getUsername, User::getInfo, User::getBalance)  // 查询字段.like(User::getUsername, "o")  // 用户名包含 "o".ge(User::getBalance, 1000);   // 余额大于等于 1000//实现查询List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);
}

条件构造器的用法总结

  1. QueryWrapper和LambdaQueryWrapper通常用来构建selectdelete、update的where条件部分
  2. UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
  3. 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper避免硬编码

Part2:自定义SQL

为什么有了MP实现自动的增删改查,以及条件构造器了,还要自定义SQL?通过两个案例解释一下。

案例1

需求:将id在指定范围的用户(例如1、2、4)的余额扣减指定值。手写sql代码如下。

<update id="updateBalanceByIds">UPDATE userSET balance = balance - #{amount}WHERE id IN<foreach collection="ids" separator="," item="id" open="(" close=")">#{id}</foreach>
</update>

我们之前想要实现更新,需要编写如上的sql语句,虽然Wrapper可以更加简单的实现,但是Wrapper通过setSql实现拼接sql代码的时候,实际上是在业务代码中编写了Sql代码,这在大公司中是不允许的,一般只允许在xml中编写Sql代码。

案例2

那我们就只能被迫手写所有Sql代码了吗,即使如果sql语句很复杂其实用MP可以很轻松的编写的话呢?不光是更新,在查询中,如下面代码所示,MP其实可以不管where条件多复杂都可以快速的编写出来,但是sql语句的前半部分就不一定了,前面的SELECT不是正常在数据表中字段了,还要起别名,那这时候如果用Wrapper,就只能通过setSql()拼出来。

<select id="selectStatusCount" resultType="Map">SELECT status, COUNT(id) AS totalFROM tb_user<where><if test="name != null">AND username LIKE #{name}</if><if test="uids != null">AND id IN<foreach collection="uids" open="(" close=")" item="id" separator=",">#{id}</foreach></if></where>GROUP BY status
</select>

解决方案

有无两全之策?那就是自定义Sql,我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SOL语句中剩下的部分。
在这里插入图片描述
在这里插入图片描述
既保证了不在业务层编写Sql,遵循了企业规范,同时享受到了MP生成Sql条件的便捷特性。

Part3:IService接口

IService接口基本用法

 前面我们感受到了继承是很爽的,为了一直继承一直爽,MP为我们提供了IService接口,继承之后,一些增删改查的service代码也不用写了。比MapperBase只多不少。
在这里插入图片描述
 左上角的save是新增,第一个是新增一个,第二个接收的是一个集合,即批量新增。之前实现批量新增,需要在Mapper.xml文件里写foreach循环组装一堆数据,现在不用写了,有了这个接口,直接调用即可。比如saveOrUpdate,如果给的数据带着Id,那他就更新,不带,他就新增。
removeByIdsremoveBatchByIds (以及类似对比)都是常见的数据库操作方法,尤其在使用 MyBatis 或者类似的 ORM 框架时。这两者的主要区别通常体现在方法的命名和具体实现细节上,但在某些框架中,它们可以执行相似的操作。具体来说:

  1. removeByIds

    • 一般用于删除指定的 单个或多个 记录。
    • 该方法通常接收一个集合或数组作为参数,可以根据提供的 ID 列表删除对应的记录。
    • 适用于较简单的删除操作,可能适用于删除一个 ID 列表中的所有记录。
  2. removeBatchByIds

    • 通常是 批量删除 的语义,意味着该方法在数据库中执行的是一个批量删除操作,通常会涉及数据库性能优化(如批量执行 SQL)。
    • 在某些框架中,removeBatchByIds 可能会采用不同的数据库操作方式来提高性能
    • 如果删除的是大量数据,使用 removeBatchByIds 可能会有更好的性能表现,因为它优化了执行流程。

总结:

  • removeByIds 适用于简单的删除操作,通常是删除一个或多个 ID 对应的记录。
  • removeBatchByIds 侧重于批量删除,通常会优化批量删除的性能。

 虽然在某些框架中,这两个方法的实现方式可能相似,且可以互换使用,但通常 removeBatchByIds 强调了处理大量数据时的性能优化。如果数据操作达到几千个,用Batch性能好一点。

 大多数时候我们根据Id进行操作,但遇到复杂条件,我们要用Wrapper,为了传Wrapper,我们就要new Wrapper,这样的话就繁琐了一点,所以service就提供了lambdaQuery()的方法,可以得到lambdaQuery()的chain的Wrapper,也就是链式编程的Wrapper,也就是说用它可以直接基于lambdaQuery()做查询了,不用自己去new了,更加方便了。遇到一般用Id的就用普通方法,遇到复杂的就用Lambda的。
注意 我们现在修改之前的业务层,用之前业务层的接口继承IService接口,但是我们知道,我们需要把业务层的接口所定义的函数都实现,那我现在要把IService中所有的方法都实现吗?其实MP不光给我们提供了IService接口,还提供了IService默认的实现类ServiceImpl。
在这里插入图片描述
一句话:接口继承接口,实现类继承实现类。

MP的Service接口基本用法的使用流程是怎样的?

  1. 自定义 Service 接口,继承 IService 接口:
public interface IUserService extends IService<User> { //User 是实体类。// 你可以在这里定义自定义的方法
}
  1. 自定义 Service 实现类,实现自定义接口并继承 ServiceImpl 类:
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {//UserMapper继承BaseMapper// 你可以在这里实现 IUserService 接口中的自定义方法
}

项目结构如下:
在这里插入图片描述
为了测试一下:
我们找到我们定义的接口IUserService,鼠标悬停在接口名代码上,Alt+Enter,创建测试IUserServiceTest.java

@SpringBootTest
class IUserServiceTest {@Autowiredprivate IUserService userService;@Testvoid testSaveUser(){User user = new User();user.setId(5L);user.setUsername("LiLei");user.setPassword("123");user.setPhone("18688990011");user.setBalance(200);user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userService.save(user);}@Test void testQuery(){List<User> users = userService.listByIds(List.of(1L, 2L, 4L));users.forEach(System.out::println);}}

实战案例

编号接口描述请求方式请求路径请求参数返回值
1新增用户POST/users用户表单实体
2删除用户DELETE/users/{id}用户id
3根据 id 查询用户GET/users/{id}用户id用户VO
4根据 id 批量查询GET/users用户id集合用户VO集合
5根据 id 扣减余额PUT/users/{id}/deduction/{money}用户id, 扣减金额

为了做测试 做点准备工作

准备工作

引入几个依赖

<!--swagger-->
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.1.0</version>
</dependency>
<!--web-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

配置swagger信息(直接复制到application.yaml):

knife4j:enable: trueopenapi:title: 用户管理接口文档description: "用户管理接口文档"email: zhanghuyi@itcast.cnconcat: 虎哥url: https://www.itcast.cnversion: v1.0.0group:default:group-name: defaultapi-rule: packageapi-rule-resources:- com.itheima.mp.controller

然后,接口需要两个实体:

  • UserFormDTO:代表新增时的用户表单 (Data Transfer Object 数据传输对象)
  • UserVO:代表查询的返回结果 (Value Object 值对象)

首先是UserFormDTO:

package com.itheima.mp.domain.dto;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "用户表单实体")
public class UserFormDTO {@ApiModelProperty("id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("密码")private String password;@ApiModelProperty("注册手机号")private String phone;@ApiModelProperty("详细信息,JSON风格")private String info;@ApiModelProperty("账户余额")private Integer balance;
}

然后是UserVO:与一般实体User不同在于,比如相对于数据库表中的字段,这里不涉及密码,因为不想把密码从数据库中读出

package com.itheima.mp.domain.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "用户VO实体")
public class UserVO {@ApiModelProperty("用户id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("详细信息")private String info;@ApiModelProperty("使用状态(1正常 2冻结)")private Integer status;@ApiModelProperty("账户余额")private Integer balance;
}

开始基本用法实战

创建UserController.java

package com.itheima.mp.controller;import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;import java.util.List;@Api(tags = "用户管理接口")
@RequiredArgsConstructor //Lombok提供的一个注解。Lombok会为类自动生成一个构造函数,构造函数的参数包括所有声明为 final 的字段和使用 @NonNull 注解的非 final 字段。为下面的userService 我们没有用@Autowired注入,使用Spring推荐的构造函数注入 
@RestController
@RequestMapping("users")
public class UserController {private final IUserService userService;//一个类的成员变量很多,怎样让Lombok知道哪些我们想让它帮我们注入呢,加个final,final修饰成员变量创建类时必须初始化。@PostMapping@ApiOperation("新增用户")public void saveUser(@RequestBody UserFormDTO userFormDTO){//@RequestBody 接收JSON格式// 1.转换DTO为POUser user = BeanUtil.copyProperties(userFormDTO, User.class);// 2.新增userService.save(user);}@DeleteMapping("/{id}")@ApiOperation("删除用户")public void removeUserById(@PathVariable("id") Long userId){userService.removeById(userId);}@GetMapping("/{id}")@ApiOperation("根据id查询用户")public UserVO queryUserById(@PathVariable("id") Long userId){// 1.查询用户User user = userService.getById(userId);// 2.处理voreturn BeanUtil.copyProperties(user, UserVO.class);}@GetMapping@ApiOperation("根据id集合查询用户")public List<UserVO> queryUserByIds(@RequestParam("ids") List<Long> ids){// 1.查询用户List<User> users = userService.listByIds(ids);// 2.处理voreturn BeanUtil.copyToList(users, UserVO.class);}
}

可以看到上述接口都直接在controller即可实现,无需编写任何service代码,非常方便。

不过,一些带有业务逻辑的接口则需要在service中自定义实现了。例如下面的需求:

  • 根据id扣减用户余额

这看起来是个简单修改功能,只要修改用户余额即可。但这个业务包含一些业务逻辑处理:

  • 判断用户状态是否正常
  • 判断用户余额是否充足

这些业务逻辑都要在service层来做,另外更新余额需要自定义SQL,要在mapper中来实现。因此,我们除了要编写controller以外,具体的业务还要在service和mapper中编写。

首先在UserController.java中定义一个方法:

@PutMapping("{id}/deduction/{money}")
@ApiOperation("扣减用户余额")
public void deductBalance(@PathVariable("id") Long id, @PathVariable("money")Integer money){userService.deductBalance(id, money);
}

然后是UserService接口(注意这里是从业务层方面说叫UserService接口,代码方面名叫IUserService ):

package com.itheima.mp.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;public interface IUserService extends IService<User> {void deductBalance(Long id, Integer money);
}

最后是UserServiceImpl实现类:

package com.itheima.mp.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic void deductBalance(Long id, Integer money) {// 1.查询用户User user = getById(id);// 2.判断用户状态if (user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常");}// 3.判断用户余额if (user.getBalance() < money) {throw new RuntimeException("用户余额不足");}// 4.扣减余额baseMapper.deductMoneyById(id, money);}
}

最后是mapper:

@Update("UPDATE user SET balance = balance - #{money} WHERE id = #{id}")
void deductMoneyById(@Param("id") Long id, @Param("money") Integer money);

IService的Lambda查询实战

需求:实现一个根据复杂条件查询用户的接口,查询条件如下

  • name:用户名关键字,可以为空
  • status:用户状态,可以为空
  • minBalance:最小余额,可以为空
  • maxBalance:最大余额,可以为空

可以理解成一个用户的后台管理界面,管理员可以自己选择条件来筛选用户,因此上述条件不一定存在,需要做判断。
一般的语法:

<select id="queryUsers" resultType="com.itheima.mp.domain.po.User">SELECT *FROM tb_user<where><if test="name != null">AND username LIKE #{name}</if><if test="status != null">AND status = #{status}</if><if test="minBalance != null and maxBalance != null">AND balance BETWEEN #{minBalance} AND #{maxBalance}</if></where>
</select>

如果我们还用注解来接受参数,参数太多,这时候太麻烦了,我们首先需要定义一个查询条件实体,UserQuery实体:

package com.itheima.mp.domain.query;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery {@ApiModelProperty("用户名关键字")private String name;@ApiModelProperty("用户状态:1-正常,2-冻结")private Integer status;@ApiModelProperty("余额最小值")private Integer minBalance;@ApiModelProperty("余额最大值")private Integer maxBalance;
}

接下来我们在UserController中定义一个controller方法:

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){// 1.组织条件String username = query.getName();Integer status = query.getStatus();Integer minBalance = query.getMinBalance();Integer maxBalance = query.getMaxBalance();LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda().like(username != null, User::getUsername, username).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance);// 2.查询用户List<User> users = userService.list(wrapper);// 3.处理voreturn BeanUtil.copyToList(users, UserVO.class);
}

在组织查询条件的时候,我们加入了 username != null 这样的参数,意思就是当条件成立时才会添加这个查询条件,类似Mybatis的mapper.xml文件中的<if>标签。这样就实现了动态查询条件效果了。

不过,上述条件构建的代码太麻烦了。
因此Service中对LambdaQueryWrapperLambdaUpdateWrapper的用法进一步做了简化。我们无需自己通过new的方式来创建Wrapper,而是直接调用lambdaQuerylambdaUpdate方法:

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){// 1.组织条件String username = query.getName();Integer status = query.getStatus();Integer minBalance = query.getMinBalance();Integer maxBalance = query.getMaxBalance();// 2.查询用户List<User> users = userService.lambdaQuery().like(username != null, User::getUsername, username).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance).list();// 3.处理voreturn BeanUtil.copyToList(users, UserVO.class);
}

可以发现lambdaQuery方法中除了可以构建条件,还需要在链式编程的最后添加一个list(),这是在告诉MP我们的调用结果需要是一个list集合。这里不仅可以用list(),可选的方法有:

  • .one():最多1个结果
  • .list():返回集合结果
  • .count():返回计数结果

MybatisPlus会根据链式编程的最后一个方法来判断最终的返回结果。

与lambdaQuery方法类似,IService中的lambdaUpdate方法可以非常方便的实现复杂更新业务。例如下面的需求:

需求:改造根据id修改用户余额的接口,要求如下

  • 如果扣减后余额为0,则将用户status修改为冻结状态(2)

也就是说我们在扣减用户余额时,需要对用户剩余余额做出判断,如果发现剩余余额为0,则应该将status修改为2,这就是说update语句的set部分是动态的。

@Override
@Transactional
public void deductBalance(Long id, Integer money) {// 1.查询用户User user = getById(id);// 2.校验用户状态if (user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常!");}// 3.校验余额是否充足if (user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}// 4.扣减余额 update tb_user set balance = balance - ?int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance) // 更新余额.set(remainBalance == 0, User::getStatus, 2) // 动态判断,是否更新status.eq(User::getId, id).eq(User::getBalance, user.getBalance()) // 乐观锁.update();
}

批量新增

相关文章:

黑马微服务开发与实战学习笔记_MybatisPlus_P2核心功能

系列博客目录 文章目录 系列博客目录Part1:条件构造器案例 基于QueryWrapper的查询案例 基于UpdateWrapper的查询条件构造器的用法总结 Part2:自定义SQL案例1案例2解决方案 Part3:IService接口IService接口基本用法实战案例准备工作开始基本用法实战IService的Lambda查询实战 批…...

华为云域名网站修改DNS服务器教程

修改单个域名的DNS服务器 登录域名注册控制台。 进入“域名列表”页面。 在域名列表中,单击“域名”列的待修改DNS服务器的域名。 进入域名信息页面。 图1 域名信息 在域名信息页面,单击“DNS服务器”后的“修改”,进入“修改DNS服务器”页面。 图2 修改DNS服务器 在…...

Redis 基础、Redis 应用

Redis 基础 什么是 Redis&#xff1f; Redis &#xff08;REmote DIctionary Server&#xff09;是一个基于 C 语言开发的开源 NoSQL 数据库&#xff08;BSD 许可&#xff09;。与传统数据库不同的是&#xff0c;Redis 的数据是保存在内存中的&#xff08;内存数据库&#xf…...

三分钟掌握MySQL-MVCC底层原理

MVCC介绍 mvcc是mysql为了解决脏读、不可重复读等事务之间读写问题而诞生的&#xff1b;它替代了一些场景下的低效锁&#xff0c;在保证隔离性的基础上&#xff0c;提升了读取效率和并发性。 MVCC实现 在mysql中mvcc是基于mysql的undo log和readview来实现的。 undo log 在…...

CSS 快速上手

目录 一. CSS概念 二. CSS语法 1. 基本语法规范 2. CSS的三种引入方式 (1) 行内样式 (2) 内部样式表 (3) 外部样式表 3. CSS选择器 (1) 标签选择器 (2) 类选择器 (3) id选择器 (4) 通配符选择器 (5) 复合选择器 <1> 空格 <2> 没有空格 <3> &q…...

51c视觉~YOLO~合集4

我自己的原文哦~ https://blog.51cto.com/whaosoft/12512597 1、Yolo8 1.1、检测PCB元件 技术世界正在以惊人的速度发展&#xff0c;而这种转变的核心是一个革命性的工具 — 计算机视觉。它最有趣的应用之一是电子印刷电路板 &#xff08;PCB&#xff09; 的检测和分析。本文…...

深入浅出:PHP函数的定义与使用

文章目录 前言什么是函数定义函数语法示例 调用函数示例 参数传递按值传递示例按引用传递示例默认参数示例可变数量的参数示例 返回值示例 变量作用域全局作用域示例局部作用域示例静态作用域示例 匿名函数示例闭包示例 递归函数示例 内置函数常见内置函数示例 用户自定义函数示…...

前端调试实践

作者&#xff1a;效能研发部 黄泽平 前言 在日常调试问题中&#xff0c;相信我们很多人都是用console去排查相关的问题&#xff0c;虽然问题也可以排查出来&#xff0c;但是有时它的效率并不高。这篇文章主要讲解关于断点和一些日常调试技巧的内容&#xff0c;方便你在日后调…...

芯科科技突破性超低功耗Wi-Fi 6和低功耗蓝牙5.4模块加速设备部署

致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;今日宣布推出SiWx917Y超低功耗Wi-Fi 6和低功耗蓝牙&#xff08;Bluetooth LE&#xff09;5.4模块。 作为成功的第二代无线开发平台的新产品&…...

Matlab自学笔记四十三:使用函数拆分日期时间型数据的子信息:年、月、日、时、分、秒

使用函数拆分日期时间型数据的子信息&#xff1a;年、月、日、时、分、秒&#xff0c;函数包括年year&#xff0c;季度quarter&#xff0c;月month&#xff0c;周week&#xff0c;日day&#xff0c;时hour&#xff0c;分minute&#xff0c;秒second&#xff0c;年月日ymd&#…...

【NLP高频面题 - LLM架构篇】大模型使用SwiGLU相对于ReLU有什么好处?

【NLP高频面题 - LLM架构篇】大模型使用SwiGLU相对于ReLU有什么好处&#xff1f; 重要性&#xff1a;★★★ &#x1f4af; NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化…...

【Python爬虫实战】轻量级爬虫利器:DrissionPage之SessionPage与WebPage模块详解

&#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、SessionPage &#xff08;一&#xff09;SessionPage 模块的基本功能 &#xff08;二&#xff09;基本使…...

python查找大文件

完整代码,不仅会捕获错误,还会输出大于 1MB 文件的大小(以 MB 为单位),并跳过访问受限或已删除的文件。 代码 import os# 查找当前目录及子目录下大于 1MB 的文件,并输出文件大小 for root, dirs, files in os.walk(.):for name in files:...

秒懂:使用js验证hash, content hash , chunk hash的区别

一、使用js验证hash, content hash , chunk hash的区别 1、计算一般的 Hash&#xff08;以简单字符串为例&#xff09; 使用crypto-js库来进行哈希计算&#xff0c;需提前引入npm install crypto-js库。 crypto-js&#xff1a; 是一个JavaScript加密算法库&#xff0c;用于实…...

RabbitMQ消息可靠性保证机制6--可靠性分析

在使用消息中间件的过程中&#xff0c;难免会出现消息错误或者消息丢失等异常情况。这个时候就需要有一个良好的机制来跟踪记录消息的过程&#xff08;轨迹溯源&#xff09;&#xff0c;帮助我们排查问题。 在RabbitMQ中可以使用Firehose实现消息的跟踪&#xff0c;Firehose可…...

【NoSQL数据库】MongoDB数据库——集合和文档的基本操作(创建、删除、更新、查询)

目录 一、MongoDB数据库原理 二、MongoDB数据库和集合基本操作&#xff08;增删改查&#xff09; 三、MongoDB数据库的文档基本操作&#xff08;增删改&#xff09; 四、学习笔记 往期文章&#xff1a;【NoSQL数据库】MongoDB数据库的安装与卸载-CSDN博客 一、MongoDB数据…...

IDL学习笔记(二)IDL处理卫星数据

IDL处理卫星数据 HDF文件数据集属性通用属性 常用HDF4操作函数常用的HDF5操作函数读取HDF文件的一般步骤 HDF4文件读取-----数据信息查询HDF4文件读取示例-----目标数据TIFF输出提取modis产品中数据&#xff0c;与某一点经纬度最接近的点有效结果&#xff0c;并按每行内容为日期…...

用点云信息来进行监督目标检测

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;传知代码 欢迎大家点赞收藏评论&#x1f60a; 目录 概述问题分析Making Lift-splat work well is hard深度不准确深度过拟合不准确的BEV语义 模型总体框架显性深度监督 深度细化模块演示效果核心…...

Python编写api接口读取电商商品详情数据示例

以下是一个使用 Python 的 Flask 框架来编写一个简单的 API 接口&#xff0c;用于读取模拟的电商商品详情数据的示例代码。这里假设商品详情数据是存储在一个简单的字典中模拟数据库存储&#xff0c;实际应用中你需要连接真正的数据库&#xff08;如 MySQL、MongoDB 等&#xf…...

用纯 CSS 实现网格背景

是不是在日常开发中经常遇到实现网格的需求&#xff0c;网格通常对网页中展示的元素能起到很好的定位和对齐作用。 这里介绍如何只通过 CSS 来实现这个需求&#xff1f; 使用背景图​ 这里我们的背景图使用 SVG 来创建&#xff0c;首先&#xff0c;创建绘出一个正方形&#xff…...

CNN+LSTM+AM研究方向初尝试

CNNLSTMAM研究方向初尝试 简单介绍 CNN CNN 的基本结构 卷积层&#xff08;Convolutional Layer&#xff09;&#xff1a; 该层通过卷积操作提取输入数据的特征。卷积操作使用多个卷积核&#xff08;滤波器&#xff09;对输入图像进行局部感知&#xff0c;从而识别出边缘、纹…...

对比 LiveData 和 Flow 的实现方式

前一段忙完了鸿蒙,现在又开始 Android 开发了。由于之前公司都是都是偏传统开发方式,基本都是 Java 开发 Android 那一套。现在开始学习现代 Android 开发了。 对比 LiveData 和 Flow 的实现方式 在 Android 开发中,LiveData 和 Flow 都可以用来管理异步数据流和实现 UI 的…...

React.memo 和useMemo 的区别

React.memo 和 useMemo 都是 React 中的性能优化工具&#xff0c;但它们的用途和工作原理不同。以下是它们的主要区别&#xff1a; 1. React.memo React.memo 是一个高阶组件&#xff08;HOC&#xff09;&#xff0c;用于优化组件的渲染&#xff0c;防止不必要的重新渲染。当组…...

视频码率到底是什么?详细说明

视频码率&#xff08;Video Bitrate&#xff09;是指在单位时间内&#xff08;通常是每秒&#xff09;传输或处理的视频数据量&#xff0c;用比特&#xff08;bit&#xff09;表示。它通常用来衡量视频文件的压缩程度和质量&#xff0c;码率越高&#xff0c;视频质量越好&#…...

CentOS7停更后,如何配置国内Yum源、镜像源

CentOS7停更后&#xff0c;如何配置国内Yum源、镜像源 yum介绍步骤1. 备份原有的yum源文件2. 下载国内Yum源文件3. 清除缓存并更新Yum源4. 使用国内Yum源 yum介绍 Yum&#xff08;Yellowdog Updater Modified&#xff09;是一个在CentOS和Red Hat Enterprise Linux&#xff08…...

黑石云|Linux-基础口令

在Linux系统中&#xff0c;设置和管理口令&#xff08;密码&#xff09;是确保系统安全性的重要环节。以下是一些关于Linux基础口令的详细解释和操作指南&#xff1a; 一、口令设置命令 passwd命令 功能&#xff1a;用于更改当前用户的密码。 使用方法&#xff1a;在终端中输…...

如何配置Github并在本地提交代码

前提: 可以流畅访问github, 需要一些上网技巧, 这就自行处理了 申请一个github账号 Github官网地址 首先就是邮箱注册啦, github没有对邮箱的限制, 只要是能收邮件的就ok, qq邮箱, 163等都可以使用. 然后和普通注册账号一样, 一路填写需要的信息, 验证邮箱即可. 如何新增代…...

UiPath API接口说明

Swagger网址 私有云网址&#xff08;企业版&#xff09; https://企业/swagger/index.html 公有云网址&#xff08;社区版&#xff09; https://cloud.uipath.com/linan/LinanZhang/orchestrator_/swagger/index.html#/ 常见问题 Swagger页面测试请求时报错“You are not a…...

Ubuntu22.04上kdump和crash的使用

0.前言 1.引用&#xff1a; 解决Linux内核问题实用技巧之 - Crash工具结合/dev/mem任意修改内存-腾讯云开发者社区-腾讯云 解决Linux内核问题实用技巧之-dev/mem的新玩法-腾讯云开发者社区-腾讯云 ubuntu内核转储分析——kdump和crash的下载和使用_ubuntu kdump-CSDN博客 U…...

【2025最新计算机毕业设计】基于SSM+Vue中华传统文化吟诵知识学习系统

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…...

智能社区服务小程序+ssm(lw+演示+源码+运行)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了智能社区服务小程序的开发全过程。通过分析智能社区服务小程序管理的不足&#xff0c;创建了一个计算机管理智能社区服务小程序的方案。文章介绍了智能社区服务…...

windows10电脑缺少dll文件的解决方案,系统缺少dll修复指南

在使用Windows 10操作系统时&#xff0c;有时会遇到由于缺少某些动态链接库&#xff08;Dynamic Link Library, 简称DLL&#xff09;文件而导致程序无法正常运行的问题。本指南将介绍几种解决此类问题的方法。 什么是DLL文件&#xff1f; DLL文件是Windows系统中的一种特殊类型…...

【设计模式系列】工厂方法模式(二十一)

一、什么是工厂方法模式 工厂方法模式&#xff08;Factory Method Pattern&#xff09;是一种创建型设计模式&#xff0c;其核心目的是定义一个创建对象的接口&#xff0c;但让实现这个接口的子类来决定实例化哪一个类。工厂方法模式让类的实例化推迟到子类中进行&#xff0c;…...

etcd资源超额

集群内apiserver一直重启&#xff0c;重启kubelet服务后查看日志发现一下报错&#xff1a; Error from server: etcdserver: mvcc: database space exceeded 报错原因&#xff1a; etcd服务未设置自动压缩参数&#xff08;auto-compact&#xff09; etcd 默认不会自动 compa…...

数据结构与算法学习笔记----DFS

数据结构与算法学习笔记----DFS author: 明月清了个风 first publish time: 2024.12.4 revised: 2024.12.5 - 加了Acwing 843. n-皇后问题 。 ps⛹感觉DFS的题基本的思想就是递归&#xff0c;但是每题都有不一样的地方&#xff0c;每一题的思路和模拟过程都单独写在每一题里…...

力扣54.螺旋矩阵

题目描述 题目链接54. 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a;…...

【原生js案例】webApp实现一个分享到的功能

这种分享到的效果很常见&#xff0c;在我们的网站上。鼠标滑入展示&#xff0c;滑出就隐藏。现在我们使用定时器功能来实现这种滑动效果。 感兴趣的可以关注下我的系列课程【webApp之h5端实战】&#xff0c;里面有大量的css3动画效果制作原生知识分析&#xff0c;讲解&#xf…...

iPhone手机清理软件:相册清理大师推荐

随着智能手机成为我们日常生活的必需品&#xff0c;手机中的数据日益膨胀&#xff0c;尤其是照片和视频这类容易积累的文件。对于iPhone用户来说&#xff0c;管理这些文件&#xff0c;特别是清理相册变得尤为重要。本文将介绍一款备受推崇的iPhone手机清理软件——CleanMyPhone…...

Javaweb梳理21——Servlet

Javaweb梳理21——Servlet 21 Servlet21.1 简介21.3 执行流程21.4 生命周期4.5 方法介绍21.6 体系结构21.7 urlPattern配置21.8 XML配置 21 Servlet 21.1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。使用Servlet就可以实现&…...

Serverless 时代

前端的边界探索&#xff0c;从客户端展开&#xff0c;以跨端为目标&#xff0c;用一套 JavaScript 代码生成多端平台&#xff0c;以此来实现大前端的统一。虽然在这条路上还不算尽善尽美&#xff0c;但各家公司的跨端方案已基本趋于成熟&#xff0c;并且已经运用到生产环境中。…...

docker安装clickhouse副本集群

docker安装clickhouse副本集群 1、clickhouse副本集群搭建1.1、docker安装zookeeper集群1.1.1、zookeeper第一个节点安装1.1.2、zookeeper第二个节点安装1.1.3、zookeeper第三个节点安装1.1.4、zookeeper客户端命令 2、Clickhouse副本集群搭建2.1、clickhouse搭建2.2、验证集群…...

详解AI网关助力配电房实现智能化管控应用

​对于一些建设年份久远的老旧配电房&#xff0c;由于配套降温散热设施设备不完善、线路设备老化等因素&#xff0c;极易出现因环境过热而影响设备正常稳定运行&#xff0c;进而导致电气故障甚至火灾等事故产生。 基于AI网关的配电房智能监控及管理 针对配电房的实时安全监测及…...

uniapp调用腾讯定位api

1、注册腾讯地址api接口&#xff0c;创建应用获取key WebService API | 腾讯位置服务 2、配置获取方法getCity // 定位服务getCity(latitude, longitude) {const key XXXX-XXXX-XXXX-XXXX-XXXX; // 替换为你的腾讯位置服务密钥const url /apis.map.qq.com/ws/geocoder/v1/…...

映射vim键位,基本功能键位表(未更完)

键位映射&#xff1a;建议使用jj代替esc,毕竟esc离手那么远 linux下修改方法是&#xff1a;vim /etc/vim/vimrc 在该文件尾添加inoremap jj <Esc>该方法可以同样可以用到其他键位映射上 i&#xff1a;表示这个映射是在插入模式&#xff08;insert mode&#xff09;下有效…...

【Python】爬虫实战03:自动化抢票脚本【某麦网】

1. 脚本介绍 1.1 背景介绍 在这个数字化时代&#xff0c;演唱会、体育赛事和各种活动的门票销售往往在线上进行。由于热门活动的高需求和门票的有限供应&#xff0c;抢票成为了一场激烈的竞争。许多粉丝和爱好者经常因为手速不够快或网络延迟而错失购票机会。为了提高抢票的成…...

AspNet WebAPI 模型绑定问题

继承System.Web.Http.ApiController的Action的Model如果被[Serializable]定义&#xff0c;会导致Model的字段无法绑定。 Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll [Serializable] public class Model {public string id { get; set; } }public MyA…...

ISAAC SIM踩坑记录--添加第三方3D场景

ISAAC SIM仿真首先就是要有合适的3D场景&#xff0c;官方提供了一些场景&#xff0c;如果不能满足要求&#xff0c;那就只能自己建。 对于我这种不会3D建模的菜鸟&#xff0c;只能到网上下载了&#xff0c;sketchfab就是一个不错的平台&#xff0c;有不少免费资源可以下载。 …...

Linux中Crontab(定时任务)命令详解

文章目录 Linux中Crontab&#xff08;定时任务&#xff09;命令详解一、引言二、Crontab的基本使用1、Crontab命令格式2、Crontab常用操作 三、Crontab的配置与服务管理1、配置Crontab2、服务管理 四、使用示例1、每天凌晨2点备份网站数据2、每周一凌晨3点清理临时文件3、每月的…...

在Ubuntu中运行和管理AppImage

文章目录 什么是AppImage&#xff1f;如何在Ubuntu中运行AppImage&#xff1f;如何管理AppImage&#xff1f;安装AppImageLauncher如何添加AppImage到系统&#xff1f;如何从系统中移除AppImage&#xff1f; 总结 什么是AppImage&#xff1f; AppImage是一种将应用程序打包为单…...

2024年12月大语言模型最新对比:GPT-4、Claude 3、文心一言等详细评测

前言 随着人工智能技术的快速发展&#xff0c;大语言模型(LLM)已经成为了技术领域最热门的话题。本文将详细对比目前主流的大语言模型&#xff0c;帮助大家选择最适合的工具。 一、OpenAI GPT系列 1. GPT-4 核心优势&#xff1a; 多模态理解能力强 逻辑推理能力出色 创造…...