Mybatis-Plus中update更新操作用法

news2025/2/13 12:46:28

目录

    • 一、前言
    • 二、update
      • 1、关于修改的4个条件构造器
      • 2、UpdateWrapper【用法示例】
      • 3、LambdaUpdateWrapper【用法示例】
      • 4、UpdateChainWrapper【 用法示例】
      • 5、LambdaUpdateChainWrapper【 用法示例】
      • 6、updateById 和 updateBatchById
      • 7、Mybatis-plus设置某个字段值为null的方法总结
    • 三、saveOrUpdate
      • 1、saveOrUpdate 【用法示例】
      • 2、saveOrUpdateBatch【用法示例】
      • 3、批量插入优化
    • 四、防全表更新与删除插件

一、前言

在Mybatis-Plus官网当中并没有对于update进行针对性的详细讲解以及其使用,很多初级小白都用不明白,包括我有时候都迷迷糊糊的,基于这个问题我也是下定决心好好整理一篇。本篇文章重点是通过多个案例来进行讲解,每一个案例执行出来的sql我都会放到文章当中,方便大家快速掌握并使用!

在实际开发当中我们一般都是将service的接口继承IService<T>,然后serviceImpl继承ServiceImpl<M extends BaseMapper<T>, T>,mapper接口继承BaseMapper<T>

BaseMapper相对来说方法比较少,一般都是通过service接口或者serviceImpl来使用,其update的相关方法有如下:

二、update

update方法主要有以下:

// 返回UpdateChainWrapper,主要用来链式调用
UpdateChainWrapper update();
// 返回LambdaUpdateChainWrapper ,同样是主要用来链式调用,只不过是基于Lambda的
LambdaUpdateChainWrapper lambdaUpdate();
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

参数说明

1、关于修改的4个条件构造器

Mybatis-Plus给我们提供了4个关于Java修改的条件构造器,这四个构造器的顶级父类都是Wrapper

  1. UpdateWrapper
UpdateWrapper<User> objectUpdateWrapper = new UpdateWrapper<>();
UpdateWrapper<User> update1 = Wrappers.update();
  1. LambdaUpdateWrapper:
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper();
LambdaUpdateWrapper<User> updateWrapper = new UpdateWrapper().lambda();
LambdaUpdateWrapper<User> objectLambdaUpdateWrapper = Wrappers.lambdaUpdate();
  1. UpdateChainWrapper:可以new,但是必须传入BaseMapper参数或者是传入实体类的字节码,可以通过service来声明。
@Resource
private UserService userService;

@Resource
private UserMapper userMapper;

@Test
void contextLoads() {
    UpdateChainWrapper<User> update = userService.update();
    UpdateChainWrapper<User> userUpdateChainWrapper = new UpdateChainWrapper<>(User.class);
    UpdateChainWrapper<User> userUpdateChainWrapper1 = new UpdateChainWrapper<>(userMapper);
}
  1. LambdaUpdateChainWrapper:同UpdateChainWrapper一样,可以new,但是必须传入BaseMapper参数或者是传入实体类的字节码,可以通过service来声明,LambdaUpdateChainWrapper<User> userLambdaUpdateChainWrapper = userService.lambdaUpdate();
    在这里插入图片描述

UpdateChainWrapper和LambdaUpdateChainWrapper都继承了AbstractChainWrapper,而UpdateWrapper和LambdaUpdateWrapper都继承了AbstractWrapper。AbstractChainWrapper和AbstractWrapper都继承了Wrapper。

在上面我们也了解到了Mybatis-Plus给我们提供了好几个update方法,并且传参都离不开Wrapper,下面我们将通过不同的Wrapper和不同的方法进行结合起来,彻底了解清楚什么时候该用什么方法!

2、UpdateWrapper【用法示例】

UpdateWrapper当中主要这四个方法用的比较多一点

set(String column, Object val)
set(boolean condition, String column, Object val)
setSql(String sql)
setSql(boolean condition, String sql)

参数解释:

类型参数名描述
Stringcolumn数据库当中的字段名称
Objectval需要修改的数据
booleancondition判断条件,控制该sql是否用到条件当中,假如为true代表生效
Stringsql拼接sql

(1)使用场景一:

UpdateWrapper<User> updateWrapper = Wrappers.update();
// 修改表中name字段为指定的数据
updateWrapper.set("name", "123");
// 假如age不等于空,那么我就将age修改为我指定的参数
Integer age = 66;
updateWrapper.set(age != null, "age", age);
updateWrapper.set("email", "99999@qq.com");
// 修改条件为id=5的数据
updateWrapper.eq("id", 5);
// 假如修改失败返回值为false
boolean update = userService.update(updateWrapper);

日志打印出来的sql:

UPDATE user SET name='123',age=66,email='99999@qq.com' WHERE (id = 5)

使用 boolean update(Wrapper<T> updateWrapper); 修改,他本质上就是调用的update(T updateEntity, Wrapper<T> whereWrapper);,只不过Entity传的为null!

(2)使用场景二:把所有set值全去掉,只使用UpdateWrapper作为修改的条件,然后通过Entity赋值

UpdateWrapper<User> updateWrapper = Wrappers.update();
// 修改条件为id=5的数据
updateWrapper.eq("id", 5);
User user = new User();
user.setName("wdawdwa");
user.setAge(888);
user.setEmail("dwadwad@qq.com");
// 假如修改失败返回值为false
boolean update = userService.update(user, updateWrapper);

日志打印出来的sql:

UPDATE user SET name='wdawdwa', age=888, email='dwadwad@qq.com' WHERE (id = 5)

(3)Entity之和UpdateWrapper两种赋值方式同时使用:

接下来我们进行测试看看boolean update(T updateEntity, Wrapper<T> whereWrapper); 假如同时使用两种赋值方式会是什么样的。

UpdateWrapper<User> updateWrapper = Wrappers.update();

// 修改表中name字段为指定的数据
updateWrapper.set("name", "123");
// 假如age不等于空,那么我就将age修改为我指定的参数
Integer age = 66;
updateWrapper.set(age != null, "age", age);
updateWrapper.set("email", "99999@qq.com");
// 修改条件为id=5的数据
updateWrapper.eq("id", 5);

User user = new User();
user.setName("wdawdwa");
user.setEmail("99999@qq.com");

// 假如修改失败返回值为false
boolean update = userService.update(user, updateWrapper);

日志打印出来的sql:

UPDATE user SET name='wdawdwa', age=0, email='99999@qq.com', name='123222',age=66 WHERE (id = 5)

得出结论:

  • updateWrapper和Entity同时对name进行赋值,很显然Entity根本没起到作用的哈!updateWrapper优先级要高于Entity。
  • 最终查询出来的sql是updateWrapper和Entity两种赋值方式的并集。并不会因为使用了updateWrapper.set赋值就导致整个Entity失效!

(4)现在有一个疑问需要验证一下,new出来的user并没有对email字段赋值,那么他会不会将数据库当中的email赋值为null。

下面我们进行验证,我user表有好几个字段,我只修改了两个!

UpdateWrapper<User> updateWrapper = Wrappers.update();
updateWrapper.eq("id", 5);
User user = new User();
user.setName("wdawdwa");
user.setAge(888);
boolean update = userService.update(user, updateWrapper);

日志打印出来的sql:

UPDATE user SET name='wdawdwa', age=888 WHERE (id = 5)

得出结论:

  • Mybatis-Plus会根据字段是否为null来判断条件是否生效,假如实体类当中使用的是基本类型,new出来的对象会赋初始值的,比如int默认就是0,这样就会导致我们并不想对他进行修改,但是最后却修改了。

(5)本质上假如我们不使用UpdateWrapper的set相关方法的话,其实也可以直接使用QueryWrapper的,如下:

QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
updateWrapper.eq("id", 5);
User user = new User();
user.setName("wdawdwa");
user.setAge(888);
user.setEmail("dwadwad@qq.com");
boolean update = userService.update(user, objectQueryWrapper);

日志打印出来的sql同时用UpdateWrapper是一样的:

UPDATE user SET name='wdawdwa', age=0 WHERE (id = 5)

UpdateWrapper和QueryWrapper都继承了AbstractWrapper,AbstractWrapper主要用于生成 sql 的 where 条件,AbstractWrapper又继承了Wrapper。他两个唯一的区别是:

  • UpdateWrapper实现了Update接口,这个接口提供了一些set方法
  • QueryWrapper实现了Query接口,这个接口提供了一些select方法

在这里插入图片描述
在这里插入图片描述

(6)假如我们不使用Entity也不使用UpdateWrapper的set,那sql打印出来是什么呢?

UpdateWrapper<User> updateWrapper = Wrappers.update();
// 修改条件为id=5的数据
updateWrapper.eq("id", 5);
// 假如修改失败返回值为false
boolean update = userService.update(null, updateWrapper);

运行结果:

得出结论:

  • 直接就语法异常了:语法异常userService.update并不会返回false,而是线程直接就终止了!

3、LambdaUpdateWrapper【用法示例】

UpdateWrapper和LambdaUpdateWrapper其实是一样的,都能够实现彼此的功能,只是语法不同,LambdaUpdateWrapper所有的指定column参数不再是字符串,而是SFunction函数。

(1)使用场景:

LambdaUpdateWrapper<User> objectLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// 修改条件为id=5的数据
objectLambdaUpdateWrapper.eq(User::getId, 5);
objectLambdaUpdateWrapper.set(User::getAge, 22);
objectLambdaUpdateWrapper.set(User::getName, "zhangsan");
objectLambdaUpdateWrapper.setSql("email='cece@qq.com'");

User user = new User();
user.setAge(666);
boolean update = userService.update(user, objectLambdaUpdateWrapper);

日志打印出来的sql:

UPDATE user SET age=666, age=22,name='zhangsan',email='cece@qq.com' WHERE (id = 5)

(2)原理讲解

在这里插入图片描述
在这里插入图片描述

SFunction其实就是继承了Function函数。而Function是一个函数式(Functional)接口

Function三种使用方法:

public static void main(String[] args) {
    // 匿名内部类
    Function function = new Function<User, Object>() {
        @Override
        public Object apply(User user) {
            return user.getAge();
        }
    };

    // lambda
    Function<User, Object> function1 = (a) -> a.getAge();

    // 方法引用
    Function<User, Object> function2 = User::getAge;
}

核心源码: 感兴趣的可以断点观察一下源码

(3)假如我们的get方法和表中的字段不对应,是否会出问题?

LambdaUpdateWrapper<User> objectLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// 修改条件为id=5的数据
objectLambdaUpdateWrapper.eq(User::getId, 5);
objectLambdaUpdateWrapper.set(User::getSexaa, "男");
boolean update = userService.update(objectLambdaUpdateWrapper);

日志打印出来的sql:

UPDATE user SET sex='男' WHERE (id = 5)

得出结论:

  • 实体字段名和数据库当中的列名称不一致,并不会影响赋值使用,他实际上是通过反射拿到的是@TableField当中指定的值!而并非只是简单的通过get方法名字来获取的。

4、UpdateChainWrapper【 用法示例】

(1)使用场景一:

// UpdateChainWrapper有三种创建方式
//	UpdateChainWrapper<User> userUpdateChainWrapper = new UpdateChainWrapper<>(User.class);
//	UpdateChainWrapper<User> update = new UpdateChainWrapper<>(userMapper);
User user = new User();
user.setAge(222);
UpdateChainWrapper<User> updateChainWrapper = userService.update();
updateChainWrapper.eq("id", 5)
        .set("name", "张三")
        .setSql("email='cece@qq.com'")
        .setEntity(user)
        .update();

日志打印出来的sql:

UPDATE user SET name='张三',email='cece@qq.com' WHERE age=222 AND (id = 5)

(2)使用场景二:

User user = new User();
user.setAge(222);
UpdateChainWrapper<User> updateChainWrapper = userService.update();
updateChainWrapper.eq("id", 5)
        .update(user);

日志打印出来的sql:

UPDATE user SET age=222 WHERE (id = 5)

5、LambdaUpdateChainWrapper【 用法示例】

LambdaUpdateChainWrapper同UpdateChainWrapper一模一样,只不过参数是函数式表达式,这里就不再过多叙述了。

// LambdaUpdateChainWrapper有三种创建方式
 // LambdaUpdateChainWrapper<User> userUpdateChainWrapper = new LambdaUpdateChainWrapper<>(User.class);
 // LambdaUpdateChainWrapper<User> update = new LambdaUpdateChainWrapper<>(userMapper);
 User user = new User();
 user.setAge(222);
 LambdaUpdateChainWrapper<User> userLambdaUpdateChainWrapper = userService.lambdaUpdate();
 userLambdaUpdateChainWrapper.eq(User::getId,5)
         .update(user);

日志打印出来的sql:

UPDATE user SET age=222 WHERE (id = 5)

6、updateById 和 updateBatchById

(1)updateById 使用场景:

在调用updateById方法前,需要在T entity(对应的实体类)中的主键属性上加上@TableId注解。

User user = new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);
userService.updateById(user);

日志打印出来的sql:

UPDATE user SET age=555 WHERE id=5

(2)updateBatchById 使用场景:

User user = new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);

User user1 = new User();
user1.setId(new Long(4));
user1.setAge(666);
user1.setEmail(null);

List<User> objects = new ArrayList<>();
objects.add(user);
objects.add(user1);
boolean b = userService.updateBatchById(objects);

日志打印出来的sql:

UPDATE user SET age=555 WHERE id=5
UPDATE user SET age=666 WHERE id=4

7、Mybatis-plus设置某个字段值为null的方法总结

Mybatis-Plus给我们提供的update根本没有全量修改的,都是只对不为空的进行修改,例如updateById和update使用Entity赋值的方法都是只对不为null的进行赋值修改。假如遇到需要将某个值赋为null这时候该怎么办?

方式一:在mapper.xml中写对应的sql语句

方式二:实体类对应字段添加注解

@TableField注解介绍:

  • @TableField(insertStrategy = FieldStrategy.IGNORED) 添加该注解值的字段在Mybatis-plus生成insert sql时会忽略该字段值的判断
  • @TableField(updateStrategy = FieldStrategy.IGNORED) 添加该注解值的字段在Mybatis-plus生成update sql时会忽略该字段值的判断
  • @TableField(whereStrategy = FieldStrategy.IGNORED) 添加该注解值的字段在Mybatis-plus生成sql时的where条件中会忽略该字段值的判断

可以聚合三种进行同时使用:

@TableField(insertStrategy = FieldStrategy.IGNORED,updateStrategy = FieldStrategy.IGNORED,whereStrategy = FieldStrategy.IGNORED)  

说明 FieldStrategy 的可选值:

  • FieldStrategy.NOT_NULL:不为null则更新,也就是字段值为null则不生成到sql中不更新该字段,如果字段值为""(空字符串)也是会更新的
  • FieldStrategy.NOT_EMPTY:不为空则更新,也就是该字段值为null或为""(空字符串)都不会更新
  • FieldStrategy.DEFAULT:默认值,和全局配置保持一致
  • FieldStrategy.IGNORED:忽略判断,该字段值不论是什么,都进行更新
  • FieldStrategy.NEVER:不做更新操作,该字段值不论是什么,都不进行更新

在email字段中设置注解,加上该注解之后,Mybatis-plus会在对应的情况下生成sql时忽略掉该字段值的判断;即该字段值不论是什么都会生成在sql中,就可以设置字段值为null了;

@TableField(value = "email", updateStrategy = FieldStrategy.IGNORED)

测试添加注解后的效果:

User user = new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);
userService.updateById(user);

日志打印出来的sql:

UPDATE user SET age=555, email=null WHERE id=5

方式三:通过条件构造器的set进行赋值

UpdateWrapper<User> updateWrapper = Wrappers.update();
updateWrapper.set("name", null);
updateWrapper.eq("id", 5);
boolean update = userService.update(updateWrapper);

方式四:Mybatis-plus 全局参数配置(yaml方式配置如下)

全局配置的值可选项和第二种方式 FieldStrategy 的可选项一致,全局配置默认值为 not_null

mybatis-plus:
  global-config:
    db-config:
      insert-strategy: ignored
      update-strategy: ignored
      select-strategy: ignored

这种方式和第二种一样可能会使用不当导致字段值为null,数据丢失;并且该方式是全局配置,对所有表的实体类所有字段都生效,危害会更严重;如果同时配置了第二种,那么优先第二种生效。

三、saveOrUpdate

saveOrUpdate方法主要有以下:

// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

参数说明:

下面进行一个一个讲解

1、saveOrUpdate 【用法示例】

方法一:

boolean saveOrUpdate(T entity);  

这个方法我就不演示了哈,通过源码已经可以看的一清二楚了,如下:

方法二:

default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
    return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
}
User user = new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);

UpdateWrapper<User> updateWrapper = Wrappers.update();
updateWrapper.set("name", "123");
boolean b = userService.saveOrUpdate(user, updateWrapper);

日志打印出来的sql:

我把user.setId(new Long(5));这一行去掉之后也是打印出来的下面的sql

UPDATE user SET age=555, name='123'

通过上面示例好像说明不了其作用,我们再来看一个示例:

User user = new User();
user.setAge(555);
user.setEmail(null);

UpdateWrapper<User> updateWrapper = Wrappers.update();
// 修改表中name字段为指定的数据
updateWrapper.set("name", "123");
// 假如不存在id为5的数据,这时候会进行新增
updateWrapper.eq("id",5);
boolean b = userService.saveOrUpdate(user, updateWrapper);

日志打印出来的sql:

UPDATE user SET age=555, name='123' WHERE (id = 5)

假如不存在id为5的数据,这时候打印出来的sql:

UPDATE user SET age=555, name='123' WHERE (id = 6)
INSERT INTO user ( id, age ) VALUES ( 1668194662817099777, 555 )

得出结论:

  • 像我们平常使用的updateByid不就是根据id来判断是新增还是修改。而这个方法说白了他就是要以updateWrapper当中所组成的where条件来判断是新增还是修改。

2、saveOrUpdateBatch【用法示例】

方法三:

default boolean saveOrUpdateBatch(Collection<T> entityList) {
    return this.saveOrUpdateBatch(entityList, 1000);
}

测试代码:数据库当中只有id为5的数据,没有id为6的数据

User user = new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);

User user1 = new User();
user1.setId(new Long(6));
user1.setAge(666);
user1.setEmail(null);

List<User> objects = new ArrayList<>();
objects.add(user);
objects.add(user1);

boolean b = userService.saveOrUpdateBatch(objects);

System.out.println("11111111111111111111");
System.out.println(b);

日志打印出来的sql:

SELECT id,name,age,email FROM user WHERE id=5
UPDATE user SET age=555 WHERE id=5
SELECT id,name,age,email FROM user WHERE id=6
INSERT INTO user ( id, age ) VALUES ( 6, 666 )

得出结论:

  • 假如是批量的,能查到就修改,查不到就新增,每条数据都是相互隔离的,谁也不影响谁

方法四:

其实方法三就是掉用的方法四,设置了batchSize 为1000。 batchSize代表的是插入批次数量。

boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

3、批量插入优化

如果大数据量(例如五千、一万)插入建议修改MySQL的JDBC连接的url为如下,开启rewriteBatchedStatements,可以优化插入速度。

url: jdbc:mysql://127.0.0.1:3306/text1?characterEncoding=UTF-8&useSSL=false&rewriteBatchedStatements=true

四、防全表更新与删除插件

在使用Mybatis-Plus的时候如果对API不是特别了解很容易导致重大事故,就拿下面的代码来说:

User user = new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);

UpdateWrapper<User> updateWrapper = Wrappers.update();
updateWrapper.set("name", "123");
boolean b = userService.saveOrUpdate(user, updateWrapper);

日志打印出来的sql:

UPDATE user SET age=555, name='123'

本来想着只修改id为5的数据,却不料最终执行的sql连where条件都没有,导致把整张表全给修改了。针对于这个问题我们可以添加如下配置进行防范:

这是官网给我们提供的:https://baomidou.com/pages/c571bc/#blockattackinnerinterceptor

@Configuration
public class MybatisPlusConfig {
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    return interceptor;
  }
}

然后这时候再执行sql会发现直接就异常了,原因是没有where条件!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/639421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Fiddler Response私人订制,你知道多少

目录 前言 特定返回状态码的模拟 特定字段数据的模拟 修改“Customize Rules" 特定加密返回值的模拟 Fiddler的TextWizard 结束语 总结&#xff1a; 前言 在客户端接口的测试中&#xff0c;我们经常会需要模拟各种返回状态或者特定的返回值&#xff0c;常见的是用…

MySQL数据库 --- 基础篇

一、MySQL概述 1.1、数据库相关概念 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase&#xff08;DB&#xff09;数据库管理系统操纵和管理数据库的大型软件DataBase Management、System (DBMS)SQL操作关系型数据库的编程语言&#xff0c;定义了…

【网络安全】深入解析 PHP 代码审计技术与实战

前言 登录某个网站并浏览其页面时&#xff0c;注意到了一些看起来不太对劲的地方。这些迹象可能是该网站存在漏洞或被黑客入侵的标志。为了确保这个网站的安全性&#xff0c;需要进行代码审计&#xff0c;这是一项专门针对软件代码进行检查和分析的技术。在本文中&#xff0c;…

从汇编代码探究函数栈帧的创建和销毁的底层原理

人&#xff0c;只有在放弃战斗的时候才算输&#xff0c;只要坚持战斗&#xff0c;就还没输 本文收录于青花雾气-计算机基础 往期回顾 从0到1搞定在线OJ 数据在内存中的存储 计算机存储的大小端模式 目录 一、先导知识 二、函数调用堆栈 三、函数栈帧的创建 1.创建函数…

计算机图像处理—HOG 特征提取算法

一、实验介绍 1. 实验内容 本实验将学习HOG 特征提取算法。 2. 实验要点 HOG 算法HOG 算法有效的原因创建 HOG 描述符HOG 描述符中的元素数量可视化 HOG 描述符理解直方图 3. 实验环境 Python 3.6.6numpymatplotlibcv2copy 二、实验步骤 简介 正如在 ORB 算法中看到的…

机器学习—支持向量机

练习5&#xff1a;支持向量机 介绍 在本练习中&#xff0c;我们将使用支持向量机&#xff08;SVM&#xff09;来构建垃圾邮件分类器。 在开始练习前&#xff0c;需要下载如下的文件进行数据上传&#xff1a; data.tgz -包含本练习中所需要用的数据文件 其中&#xff1a; e…

华为OD机试 JavaScript 实现【计算字符串的编辑距离】【牛客练习题 HJ52】,附详细解题思路

一、题目描述 Levenshtein 距离&#xff0c;又称编辑距离&#xff0c;指的是两个字符串之间&#xff0c;由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符&#xff0c;插入一个字符&#xff0c;删除一个字符。编辑距离的算法是首先由…

后端(二):Servlet

我们上一张聊的是Tomcat&#xff0c;它其实就是一个 HTTP 服务器&#xff0c;而Servlet 是基于 Tomcat 的 原生api &#xff0c;除了 Servlet&#xff0c;后面还有聊到很多 api 。 Servlet 是什么 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xf…

【知识点复习】结构体与共用体

结构体和共用体各有什么特点&#xff1a; 1、结构体中每一个成员都有自己的内存空间&#xff0c;计算结构体大小的时候要注意内部字节对齐&#xff1b; 32位占4字节&#xff0c;64位占8字节。 结构体访问成员&#xff1a;点降级访问 2、共用体又叫联合体union&#xff0c;每一…

我的256创作纪念日

机缘 挺开心的&#xff0c;想到自己未曾写过一些非技术类的博客&#xff0c;恰巧今天刚好也是我的256创作纪念日&#xff0c;就乘着这个日子&#xff0c;写一点自己过去的收获、内心的想法和对未来的展望吧。 本人不才&#xff0c;只就读于一所民办本科之中&#xff0c;我挺不想…

ASCON:以“慢而稳”赢得NIST轻量级加密算法标准

1. 引言 自2016年以来&#xff0c;NIST一直在评估轻量级加密方法&#xff0c;并于2022年发布了入围决赛的10种轻量级加密算法&#xff1a; ASCONElephantGIFT-COFBGrain128 AEADISAPPhoton BeetleRomulusSparkleTinyJambuXoodyak 在评估过程中&#xff0c;NIST重点关注&#…

使用Python把文件夹里面的图片放入一个pdf

文章目录 背景介绍代码代码分析展示 背景介绍 在看一位up主的“矩阵分析”课程的时候&#xff0c;up主的课件是以图片形式保存在QQ空间的。图片形式不便于学习&#xff0c;所以想要通过Python代码&#xff0c;把保存在“矩阵分析课件”里面的图片&#xff0c;转换为pdf&#x…

Qt函数运用

setwidget 文件 文件读写 链接 std::ifstream---std::ofstream 头文件--#include <fstream> 执行都是类&#xff0c;用这些类操作文件都要建立对象流。 1&#xff0c;建立对象流 流对象的建立有两种方式&#xff1a; &#xff08;1&#xff09;使用fstream类可以…

内网安全:Socks 代理 || 本地代理 技术.

内网安全&#xff1a;Socks 代理 || 本地代理 技术. Socks 代理又称全能代理&#xff0c;就像有很多跳线的转接板&#xff0c;它只是简单地将一端的系统连接到另外一端。支持多种协议&#xff0c;包括http、ftp请求及其它类型的请求。它分socks 4 和socks 5两种类型&#xff0…

Selenium中的隐式等待和显式等待

在Selenium中&#xff0c;“等待”在执行测试中起着重要作用。在本文中&#xff0c;您将学习Selenium中“隐式”和“显式”等待的各个方面。 在本文中&#xff0c;您将学习到 1. 为什么我们需要在selenium中等待&#xff1f; 2. 隐瞒等待 3. 明确等待 4. 流利的等待 为什么…

15.DIY可视化-拖拽设计1天搞定主流小程序-分类联动文章列表实时刷新

分类联动文章列表实时刷新 本教程均在第一节中项目启动下操作 分类联动文章列表实时刷新前言需求一:功能实现:点击首页分类,对应分类内容显示到当前页一、清空原分类界面:二. 设置选项卡三:设定展示内容字段:1.跨页面复制:文章分类组件到分类![在这里插入图片描述](https://img…

服务器安装cuda版本的pytorch+DGL

1、先创建pytorch环境&#xff1a;conda create -n ljj_torch112 python3.8 看本机的&#xff1a; 先看自己的cuda版本&#xff1a;&#xff08;最权威的看&#xff1a;nvcc --version&#xff09; 10.0的cuda于是不太符合&#xff0c;所以换一个10.2的cuda比较常用&#xff0…

【C++从入门到放弃】list深度剖析及模拟实现

&#x1f9d1;‍&#x1f4bb;作者&#xff1a; 情话0.0 &#x1f4dd;专栏&#xff1a;《C从入门到放弃》 &#x1f466;个人简介&#xff1a;一名双非编程菜鸟&#xff0c;在这里分享自己的编程学习笔记&#xff0c;欢迎大家的指正与点赞&#xff0c;谢谢&#xff01; list …

CANN黑科技解密|昇腾Ascend C编程语言 — 极简易用的算子开发体验

AI应用的大脑是神经网络&#xff0c;而构成神经网络的基石是一个个算子。为了让开发者的网络在昇腾硬件上高效运行&#xff0c;昇腾异构计算架构CANN&#xff08;Compute Architecture for Neural Networks&#xff09;提供了丰富的高性能算子库&#xff0c;包括神经网络库、线…

Python-opcua 编程(1)

任何一项新标准如果不能充分应用是不可能推广的&#xff0c;最近看了一些国外网站&#xff0c;发现类似OPC UA 的应用以及比较广泛了&#xff0c;而且有许多课程。相比之下&#xff0c;我国OPCUA 标准的普及工作仍然停留在概述的阶段&#xff0c;为此&#xff0c;我将逐步介绍一…