SSM - Springboot - MyBatis-Plus 全栈体系(三十一)

news2025/1/23 17:43:53

第七章 MyBatis-Plus

二、MyBatis-Plus 核心功能

1. 基于 Mapper 接口 CRUD

通用 CRUD 封装 BaseMapper (opens new window)接口, Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器! 内部包含常见的单表操作!

1.1 Insert 方法
// 插入一条记录
// T 就是要插入的实体对象
// 默认主键生成策略为雪花算法(后面讲解)
int insert(T entity);
类型参数名描述
Tentity实体对象
1.2 Delete 方法
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 ID 删除
int deleteById(Serializable id);

// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
类型参数名描述
Wrapperwrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Serializableid主键 ID
Map<String, Object>columnMap表字段 map 对象
1.3 Update 方法
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity,
            @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);

// 根据 ID 修改  主键属性必须有值
int updateById(@Param(Constants.ENTITY) T entity);
类型参数名描述
Tentity实体对象 (set 条件值,可为 null)
WrapperupdateWrapper实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
1.4 Select 方法
// 根据 ID 查询
T selectById(Serializable id);

// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
类型参数名描述
Serializableid主键 ID
WrapperqueryWrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Map<String, Object>columnMap表字段 map 对象
IPagepage分页查询条件(可以为 RowBounds.DEFAULT)
1.5 自定义和多表映射
  • mybatis-plus 的默认 mapperxml 位置
mybatis-plus: # mybatis-plus的配置
  # 默认位置 private String[] mapperLocations = new String[]{"classpath*:/mapper/**/*.xml"};
  mapper-locations: classpath:/mapper/*.xml
  • 自定义 mapper 方法
public interface UserMapper extends BaseMapper<User> {

    //正常自定义方法!
    //可以使用注解@Select或者mapper.xml实现
    List<User> queryAll();
}

  • 基于 mapper.xml 实现:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace = 接口的全限定符 -->
<mapper namespace="com.alex.mapper.UserMapper">

   <select id="queryAll" resultType="user" >
       select * from user
   </select>
</mapper>

2. 基于 Service 接口 CRUD

  • 通用 Service CRUD 封装 IService (opens new window) 接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
2.1 对比 Mapper 接口 CRUD 区别
  • service 添加了批量方法
  • service 层的方法自动添加事务
2.2 使用 Iservice 接口方式
  • 接口继承 IService 接口
public interface UserService extends IService<User> {
}
  • 类继承 ServiceImpl 实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{

}
2.3 CRUD 方法介绍
保存:
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

修改或者保存:
// 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);

移除:
// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

更新:
// 根据 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);

数量:
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

查询:
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

集合:
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

3. 分页查询实现

3.1 导入分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
}
3.2 使用分页查询
@Test
public void testPageQuery(){
    //设置分页参数
    Page<User> page = new Page<>(1, 5);
    userMapper.selectPage(page, null);
    //获取分页数据
    List<User> list = page.getRecords();
    list.forEach(System.out::println);
    System.out.println("当前页:"+page.getCurrent());
    System.out.println("每页显示的条数:"+page.getSize());
    System.out.println("总记录数:"+page.getTotal());
    System.out.println("总页数:"+page.getPages());
    System.out.println("是否有上一页:"+page.hasPrevious());
    System.out.println("是否有下一页:"+page.hasNext());
}
3.3 自定义的 mapper 方法使用分页
3.3.1 方法
//传入参数携带Ipage接口
//返回结果为IPage
IPage<User> selectPageVo(IPage<?> page, Integer id);
3.3.2 接口实现
<select id="selectPageVo" resultType="xxx.xxx.xxx.User">
    SELECT * FROM user WHERE id > #{id}
</select>
3.3.3 测试
@Test
public void testQuick(){

    IPage page = new Page(1,2);

    userMapper.selectPageVo(page,2);

    long current = page.getCurrent();
    System.out.println("current = " + current);
    long pages = page.getPages();
    System.out.println("pages = " + pages);
    long total = page.getTotal();
    System.out.println("total = " + total);
    List records = page.getRecords();
    System.out.println("records = " + records);

}

4. 条件构造器使用

4.1 条件构造器作用
  • 实例代码:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John"); // 添加等于条件
queryWrapper.ne("age", 30); // 添加不等于条件
queryWrapper.like("email", "@gmail.com"); // 添加模糊匹配条件
等同于:
delete from user where name = "John" and age != 30
                                  and email like "%@gmail.com%"
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
  • 使用 MyBatis-Plus 的条件构造器,你可以构建灵活、高效的查询条件,而不需要手动编写复杂的 SQL 语句。它提供了许多方法来支持各种条件操作符,并且可以通过链式调用来组合多个条件。这样可以简化查询的编写过程,并提高开发效率。
4.2 条件构造器继承结构
4.2.1 条件构造器类结构

在这里插入图片描述

4.2.2 Wrapper : 条件构造抽象类,最顶端父类
  • AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
    • QueryWrapper : 查询/删除条件封装
    • UpdateWrapper : 修改条件封装
    • AbstractLambdaWrapper : 使用 Lambda 语法
      • LambdaQueryWrapper :用于 Lambda 语法使用的查询 Wrapper
      • LambdaUpdateWrapper : Lambda 更新封装 Wrapper
4.3 基于 QueryWrapper 组装条件

在这里插入图片描述

4.3.1 组装查询条件
@Test
public void test01(){
    //查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息
    //SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("username", "a")
            .between("age", 20, 30)
            .isNotNull("email");
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
4.3.2 组装排序条件
@Test
public void test02(){
    //按年龄降序查询用户,如果年龄相同则按id升序排列
    //SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,id ASC
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper
            .orderByDesc("age")
            .orderByAsc("id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}
4.3.3 组装删除条件
@Test
public void test03(){
    //删除email为空的用户
    //DELETE FROM t_user WHERE (email IS NULL)
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.isNull("email");
    //条件构造器也可以构建删除语句的条件
    int result = userMapper.delete(queryWrapper);
    System.out.println("受影响的行数:" + result);
}
4.3.4 and 和 or 关键字使用(修改)
@Test
public void test04() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改
    //UPDATE t_user SET age=?, email=? WHERE username LIKE ? AND age > ? OR email IS NULL)
    queryWrapper
            .like("username", "a")
            .gt("age", 20)
            .or()
            .isNull("email");
    User user = new User();
    user.setAge(18);
    user.setEmail("user@gmail.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("受影响的行数:" + result);
}
4.3.5 指定列映射查询
@Test
public void test05() {
    //查询用户信息的username和age字段
    //SELECT username,age FROM t_user
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("username", "age");
    //selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为null
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}
4.3.6 condition 判断组织条件
 @Test
public void testQuick3(){

    String name = "root";
    int age = 18;

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //判断条件拼接
    //当name不为null拼接等于, age > 1 拼接等于判断
    //方案1: 手动判断
    if (!StringUtils.isEmpty(name)){
        queryWrapper.eq("name",name);
    }
    if (age > 1){
        queryWrapper.eq("age",age);
    }

    //方案2: 拼接condition判断
    //每个条件拼接方法都condition参数,这是一个比较运算,为true追加当前条件!
    //eq(condition,列名,值)
    queryWrapper.eq(!StringUtils.isEmpty(name),"name",name)
            .eq(age>1,"age",age);
}
4.4 基于 UpdateWrapper 组装条件
4.4.1 使用 queryWrapper
@Test
public void test04() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改
    //UPDATE t_user SET age=?, email=? WHERE username LIKE ? AND age > ? OR email IS NULL)
    queryWrapper
            .like("username", "a")
            .gt("age", 20)
            .or()
            .isNull("email");
    User user = new User();
    user.setAge(18);
    user.setEmail("user@gmail.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("受影响的行数:" + result);
}
  • 注意:使用 queryWrapper + 实体类形式可以实现修改,但是无法将列值修改为 null 值!
4.4.2 使用 updateWrapper
@Test
public void testQuick2(){

    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //将id = 3 的email设置为null, age = 18
    updateWrapper.eq("id",3)
            .set("email",null)  // set 指定列和结果
            .set("age",18);
    //如果使用updateWrapper 实体对象写null即可!
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);

}
  • 使用 updateWrapper 可以随意设置列的值!!
4.5 基于 LambdaQueryWrapper 组装条件
4.5.1 LambdaQueryWrapper 对比 QueryWrapper 优势
  • QueryWrapper 示例代码:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John")
  .ge("age", 18)
  .orderByDesc("create_time")
  .last("limit 10");
List<User> userList = userMapper.selectList(queryWrapper);
  • LambdaQueryWrapper 示例代码:
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

lambdaQueryWrapper.eq(User::getName, "John")
  .ge(User::getAge, 18)
  .orderByDesc(User::getCreateTime)
  .last("limit 10");
List<User> userList = userMapper.selectList(lambdaQueryWrapper);
  • 从上面的代码对比可以看出,相比于 QueryWrapper,LambdaQueryWrapper 使用了实体类的属性引用(例如 User::getNameUser::getAge),而不是字符串来表示字段名,这提高了代码的可读性和可维护性。
4.5.2 lambda 表达式回顾
  • Lambda 表达式是 Java 8 引入的一种函数式编程特性,它提供了一种更简洁、更直观的方式来表示匿名函数或函数式接口的实现。Lambda 表达式可以用于简化代码,提高代码的可读性和可维护性。
  • Lambda 表达式的语法可以分为以下几个部分:
  1. 参数列表: 参数列表用小括号 () 括起来,可以指定零个或多个参数。如果没有参数,可以省略小括号;如果只有一个参数,可以省略小括号。

    示例:(a, b), x ->, () ->

  2. 箭头符号: 箭头符号 -> 分割参数列表和 Lambda 表达式的主体部分。

    示例:->

  3. Lambda 表达式的主体: Lambda 表达式的主体部分可以是一个表达式或一个代码块。如果是一个表达式,可以省略 return 关键字;如果是多条语句的代码块,需要使用大括号 {} 括起来,并且需要明确指定 return 关键字。

    示例:

    • 单个表达式:x -> x * x
    • 代码块:(x, y) -> { int sum = x + y; return sum; }
  • Lambda 表达式的语法可以更具体地描述如下:
// 使用 Lambda 表达式实现一个接口的方法
interface Greeting {
    void sayHello();
}

public class LambdaExample {
    public static void main(String[] args) {

        //原始匿名内部类方式
        Greeting greeting = new Greeting() {
            @Override
            public void sayHello(int a) {
                System.out.println("Hello, world!");
            }
        };

        a->System.out.println("Hello, world!")

        // 使用 Lambda 表达式实现接口的方法
        greeting = () -> System.out.println("Hello, world!");

          System.out::println;
           () ->.XXX(); -> 类::方法名
        // 调用接口的方法
        greeting.sayHello();
    }
}
4.5.3 方法引用回顾
  • 方法引用是 Java 8 中引入的一种语法特性,它提供了一种简洁的方式来直接引用已有的方法或构造函数。方法引用可以替代 Lambda 表达式,使代码更简洁、更易读。
  • Java 8 支持以下几种方法引用的形式:
  1. 静态方法引用: 引用静态方法,语法为 类名::静态方法名
  2. 实例方法引用: 引用实例方法,语法为 实例对象::实例方法名
  3. 对象方法引用: 引用特定对象的实例方法,语法为 类名::实例方法名
  4. 构造函数引用: 引用构造函数,语法为 类名::new
  • 演示代码:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class MethodReferenceExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("John", "Tom", "Alice");
        // 使用 Lambda 表达式
        names.forEach(name -> System.out.println(name));
        // 使用方法引用
        names.forEach(System.out::println);
    }
}
4.5.4. lambdaQueryWrapper 使用案例
@Test
public void testQuick4(){

    String name = "root";
    int age = 18;

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //每个条件拼接方法都condition参数,这是一个比较运算,为true追加当前条件!
    //eq(condition,列名,值)
    queryWrapper.eq(!StringUtils.isEmpty(name),"name",name)
            .eq(age>1,"age",age);

    //TODO: 使用lambdaQueryWrapper
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //注意: 需要使用方法引用
    //技巧: 类名::方法名
    lambdaQueryWrapper.eq(!StringUtils.isEmpty(name), User::getName,name);
    List<User> users = userMapper.selectList(lambdaQueryWrapper);
    System.out.println(users);
}
4.6 基于 LambdaUpdateWrapper 组装条件
  • 使用案例:
@Test
public void testQuick2(){

    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //将id = 3 的email设置为null, age = 18
    updateWrapper.eq("id",3)
            .set("email",null)  // set 指定列和结果
            .set("age",18);

    //使用lambdaUpdateWrapper
    LambdaUpdateWrapper<User> updateWrapper1 = new LambdaUpdateWrapper<>();
    updateWrapper1.eq(User::getId,3)
            .set(User::getEmail,null)
            .set(User::getAge,18);

    //如果使用updateWrapper 实体对象写null即可!
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);
}

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

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

相关文章

LoongArch 指令集设计——单周期5条指令exp5

对应实验手册请参阅《LoongArch CPU设计实验》。 NOTE: minicpu_env/miniCPU/目录下的代码功能不全&#xff0c;是有意为之&#xff0c;无需提issue修正。mycpu_env/myCPU/目录下的代码有功能错误&#xff0c;亦是有意为之&#xff0c;无需提issue修正。 实验安排简介 // dc…

E053-web安全应用-Brute force暴力破解初级

课程分类&#xff1a; web安全应用 实验等级: 中级 任务场景: 【任务场景】 小王接到磐石公司的邀请&#xff0c;对该公司旗下的网站进行安全检测&#xff0c;经过一番检查发现该论坛的后台登录页面上可能存在万能密码漏洞&#xff0c;导致不知道账号密码也能登录后台&am…

Windows消息 队列

1、 Windows消息机制 Windows是一个消息驱动的操作系统&#xff0c;消息是用一个常量标识符来标记&#xff0c;并且有两个32Bit的消息附加信息。单击鼠标、敲击键盘&#xff0c;都会通过电脑外设向系统发送特定的中断信号&#xff0c;这个中断信息在操作系统中会转化为一个消息…

leetcode每日一题复盘(10.16~10.22)

leetcode 501 二叉搜素树中的众数 对二叉搜索树的性质还不是很熟悉,不懂得利用其性质,做题没有方法论,这是暴露出来的问题,明天重做一下98,530,501这三个题,再进行总结

33 机器学习(一):特征工程

文章目录 机器学习需要用到的包的介绍机器学习做什么深度学习做什么常见的概念 数据介绍数据类型数据的来源数据的构成 特征工程one-hot编码接口集特征提取DictVectorizerCountVectorizerTfidfVectorizer 特征处理归一化 MinMaxScaler标准化 StandardScaler标准化和归一化的对比…

mmdetection及mmengine源码结构

python中的装饰函数 所谓的函数修饰符&#xff0c;就是在函数外面再套一层函数&#xff0c; 装饰函数可以接受不同的参数类型的函数传入&#xff0c;对其进行装饰加工&#xff1b; 在需要装饰的函数前面装饰函数即可&#xff1b; 这样子做的好处在于代码的复用&#xff0c;比…

使用interrupt()中断线程

示例一 : public class Test01 extends Thread {Overridepublic void run() {while (true) {}}public static void main(String[] args) {Test01 t new Test01();t.start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.prin…

家用洗地机哪个牌子最好用?质量最好的洗地机推荐

提到家务清洁&#xff0c;相信应该是很多宝妈头疼的事儿&#xff0c;不仅工作量打&#xff0c;耗时又耗力&#xff0c;拥有一款完美的清洁工具&#xff0c;那讲大大的提升幸福指数&#xff0c;而洗地机便是当下的智能清洁神器之一。那么家用洗地机哪个牌子最好用&#xff0c;质…

竞赛 深度学习YOLO图像视频足球和人体检测 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov5算法5 数据集6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习YOLO图像视频足球和人体检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非…

使用Nginx实现采集端和数据分析平台的数据加密传输

1. 需求描述 目前鸿鹄暴露出来的重要ports如下表&#xff1a; 在实际的生产环境中&#xff0c;结合我司的使用场景&#xff0c;需要在鸿鹄前端安装proxy&#xff0c;用以解决如下两个问题&#xff1a; 1.1 实现http到https的强制跳转 企业环境中&#xff0c;一般会关闭http 80端…

精准定位——MySQL日志学习的一天【错误、二进制、查询、慢查询】

MySQL 日志是记录 MySQL 数据库服务器运行过程中的各种活动和事件的文件。它们对于监控、故障排查、性能优化和数据恢复等方面都非常重要。 回顾一下Linux中查看文件的指令操作 cat 命令&#xff1a; cat 命令用于将文件的内容一次性输出到终端。它的主要功能是将文件连接起来…

在全志R128上启用USB ADB以及无线ADB配置方法

首先在FreeRTOS的环境下&#xff0c;选择r128_c906_pro&#xff1a; source envsetup.sh lunch_rtos r128s2_pro_c906USB ADB的配置比较常规&#xff0c;注意以下几个驱动的勾选 usb device驱动adb gadget驱动adbd应用 运行menuconfig&#xff0c;选择对应的驱动以及软件包&…

Docker安装ES7.14和Kibana7.14(无账号密码)

一、Docker安装ES7.14.0 1、下载镜像 docker pull elasticsearch:7.14.0 2、docker安装7.14.0 mkdir -p /usr/local/elasticsearch/config mkdir -p /usr/local/elasticsearch/data chmod 777 -R /usr/local/elasticsearch/ echo "http.host: 0.0.0.0" >> /u…

linux下 u2net tensorrt模型部署

TensorRT系列之 Windows10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速…

搭建Redis哨兵集群

目录 一、集群结构二、准备实例和配置三、启动四、测试 一、集群结构 这里我们搭建一个三节点形成的Sentinel集群&#xff0c;来监管之前的Redis主从集群。如图&#xff1a; 三个sentinel实例信息如下&#xff1a; 节点IPPORTs1192.168.239.1027001s2192.168.239.1027002s3…

RS232协议、RS485协议

RS232、RS485总线并不是单独的协议&#xff0c;这两种是依赖于串口的协议&#xff0c;这可以让他的抗干扰能力更强、提升传输速度。统一了接口标准。编程不受影响 2.RS232协议 RS232->TTL电平 常用电平转换芯片Max232 3.RS485协议 RS485采用差分信号进行传输&#xff0…

MyBatis进行单表多表查询以及其中的${}涉及的SQL注入

目录 回顾&#xff1a; 参数占位符#{}和${} ${}唯一使用地方 使用${}造成的SQL注入漏洞 like查询 mapper中接收结果的参数 resultType和resultMap​编辑 多表查询 回顾&#xff1a; 参数占位符#{}和${} #{} 占位符语法通常用于模板引擎或动态查询语句中。它是一种更加安全的…

C++产生未定义的行为的原因分析

前言 最近一直在做QT开发&#xff0c;编程环境是VS2017和QT5.11.2 经常遇到的问题就是&#xff0c;在VS中调试程序&#xff0c;前面都是正常运行的&#xff0c;但是当关闭窗口&#xff0c;退出程序的时候&#xff0c;VS会抛出一个异常 “未加载ntdll.pdb&#xff0c;触发了一…

Nmap渗透测试指南之防火墙/IDS逃逸、信息搜集

Nmap渗透测试指南之防火墙/IDS逃逸、信息搜集 一. 防火墙/IDS逃逸本章知识点本章选项一 .关于防火墙/IDS二. 报文分段三. 指定偏移大小四. IP欺骗五. 源地址欺骗六. 源端口欺骗七. 指定发包长度八. 目标主机随机排序九. MAC地址欺骗二. 信息收集本章知识点本章脚本一. 信息搜集…

iOS代码混淆工具推荐:IPA Guard详细介绍

iOS代码混淆工具推荐&#xff1a;IPA Guard详细介绍 目录 摘要&#xff1a; 引言 正文 1. IPA Guard概述 2. IPA Guard的功能特性 3. IPA Guard的混淆模式 4. 支持的语言 5. 使用场景 总结 参考资料 总结 参考资料 摘要&#xff1a; 了解并选择合适的iOS代码混淆工…