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

Mybatis-Plus知识点详解

Mybatis-plus(简称MP),基于Mybatis的增强工具,保留了Mybatis的所有功能,同时增加了通用的CRUD,条件构造器,分页插件等等实用工具

特性

  • 即拿即用:通过通用Mapper和Service,无需编写XML既可以完成单表CURE操作

  • Lambda支持:使用Lambda表达式构建查询条件,避免硬编码字段名,提升代码安全性

  • 更多的主键策略:支持多种主键生成方式,如雪花算法,自增等等

  • 分页插件:内置分页插件,支持多种数据库,简化分页查询操作

与Mybatis相比

  • 提供大量自动化功能,如通用的CRUD,条件构造器,分页支持极大减少操作代码,提高开发效率

  • Mybatis需手动编写SQL,编写XML文件和映射接口DAO

快速入门

日志配置

  • 日志输出到标准输出流中

mybatis-plus:# mapper配置文件mapper-locations: classpath:mapper/*.xml# resultType别名,没有这个配置resultType包名要写全,配置后只要写类名type-aliases-package: com.mashang.springboot04.domain//configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

添加依赖与配置application.yml

  • 本人使用SpringBoot 2.7.18,JDK1.8:导入的依赖如下

        <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version></dependency>

  • application.yml如下:

# 也是springboot的配置文件,两个都可以用
server:port: 8080servlet:#配置根路径context-path: /
# 配置数据源
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/xiaomi_store?userSSL=false;serverTimezone=Asia/Shanghaiusername: rootpassword: root
mybatis-plus:# mapper配置文件mapper-locations: classpath:mapper/*.xml# resultType别名,没有这个配置resultType包名要写全,配置后只要写类名type-aliases-package: com.mashang.springboot03.domain

定义实体类与Mapper接口

实体类

  • 在实体类上使用Mybatis-plus的注解

  • @TableName()→指定数据库查询的表,不添加默认将类名改为下划线型数据库名

  • @TableId(name,type)→用于给主键标记,name为数据库对应名,用于指定自增算法雪花算法(Snowflake)是由Twitter开源的一种分布式ID生成算法.其核心思想是将64位的long型ID分为四个部分,分别为:符号位,时间戳,工作机器ID,序列号

@Data
@TableName("user")  // 指定数据库表名
public class User {@TableId(type = IdType.AUTO)  // 主键自增private Long id;private String name;private Integer age;
}

Mapper接口

  • Mapper接口需继承BaseMapper<T>类,则此接口即可获得所有基本的CRUD方法

public interface UserMapper extends BaseMapper<User> {// 如果需要扩展自定义方法,也可以在此添加
}

Service层与Service实现层

MP也提供了IService接口和ServiceImpl类方便在Service层使用封装好的CRUD方法

Service层

  • extends(继承)IService接口

public interface UserService extends IService<User> {// 可以在此定义更多业务方法
}

ServiceImpl层

  • 继承 ServiceImpl<UserMapper, User> 和实现 IService<User> 接口,可以直接调用封装好的 CRUD 方法

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {// 继承了 ServiceImpl 后,已拥有 BaseMapper 中所有的 CRUD 方法
}

BaseMapper接口中常用的CRUD方法

  • 即Mapper层中的常见方法,已经集成好了,直接操作数据库的原子性方法

插入操作

// 插入一条记录
int insert(T entity);

查询操作

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

删除操作

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

更新操作

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

IService接口中的常用方法

  • 即service层常见方法,业务逻辑层,可组合多个 Mapper 方法,添加事务等

插入操作(save)

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

存在更新,不存在插入(saveOrUpdate)

  • boolean saveOrUpdate(T entity);:根据@TableId标识的主键判断,若主键不存在→执行INSERT,若主键存在→执行UPDATE

  • boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);:先根据updateWrapper尝试进行更新操作,若影响行数为0,则回退到saveOrUpdate(T entity)逻辑(根据主键判断是否更新或插入)

  • saveOrUpdateBatch(Collection<T>entityList) 和 saveOrUpdateBatch(Collection<T> entityList, int batchSize):批量处理集合中的实体,逻与 saveOrUpdate(T) 一致

删除操作(Remove)

可配合@TableLogic实现逻辑删除

// 根据 Wrapper 构造的条件删除记录 支持复杂条件
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
//根据 columnMap 中的字段值匹配删除记录 仅支持等值条件,
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

更新操作(Update)

必须设置 SET 字段,如果未调用 .set(),SQL会缺少更新内容导致错误

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

查询单个对象(getOne)

若实体类配置了 @TableLogic,查询时会自动过滤已删除数deleted = 0

// 根据 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)

// 查询所有
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);

分页查询(page)

  • 分页对象Page类

    主要属性:current:当前页码,从 1 开始size:每页显示的记录数searchCount:是否执行 SELECT COUNT(*) 查询总记录数,不统计总数适用于大数据量场景

Page<User> pageParam = new Page<>(1, 10);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 25).orderByDesc(User::getCreateTime);IPage<User> userPage = userService.page(pageParam, wrapper);

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

查询记录数(count)

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

// 统计年龄大于25且状态为激活的用户数量
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 25).eq(User::getStatus, 1);int count = userService.count(wrapper);

条件构造器

  • 条件构造器用于动态生成SQL中的WHERE条件,替代手动拼接SQL语句,MP中提供了两种主要的条件构造器:QueryWrapper与LambdaQueryWrapperQueryWrapper:基于字符串名的条件构造器,写法直观,但存在字段拼写错误的风险LambdaQuertWrapped:基于Lambda表达式的构造器,避免了硬编码字段,更加推荐使用

常用方法

等于.eq()

  • 用于生成字段=值的条件

    使用字符串

new QueryWrapper<User>().eq("age", 25); // 生成 SQL: WHERE age = 25

  • 使用Lambda表达式

new LambdaQueryWrapper<User>().eq(User::getAge, 25);

不等于.nq()

  • 生成字段<>值条件

new LambdaQueryWrapper<User>().ne(User::getStatus, 0); // SQL: WHERE status <> 0

模糊查询.like()

  • 生成字段LIKE ‘%值%’条件

 new LambdaQueryWrapper<User>().like(User::getName, "张"); // SQL: WHERE name LIKE '%张%'

逻辑连接or()与and()

  • or():一般用法

new LambdaQueryWrapper<User>().eq(User::getAge, 25).or().eq(User::getName, "张三");
// 生成 SQL: WHERE age = 25 OR name = '张三'

  • 嵌套用法

new LambdaQueryWrapper<User>().or(wrapper -> wrapper.eq(User::getAge, 25).ne(User::getStatus, 0));
// 生成 SQL: OR (age = 25 AND status <> 0)

  • and():作用是拼接多个条件,用 AND 连接默认条件连接就是 AND,一般无需显式调用

动态查询

  • 在查询条件前加上布尔判断,true则执行

new LambdaQueryWrapper<User>().eq(age != null, User::getAge, age) // 当 age 不为 null 时生效.like(StringUtils.isNotBlank(name), User::getName, name); // 当 name 非空时生效

分页查询

  • MP中内置了分页插件,使用Page对象来封装分页参数和结果

  • 在Springboot中通过配置类启动分页插件

    启用 MyBatis-Plus 的分页功能,使得在查询时可以直接使用分页方法

@Configuration
public class MyBatisPlusConfig {// MybatisPlus的配置@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 在拦截器中加入了一个分页的拦截器// 指定数据库类型为 MySQLinterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 20);
Page<User> pageParam = new Page<>(1, 10);
IPage<User> userPage = userService.page(pageParam, wrapper);

进阶操作

敏感字段屏蔽

  • 某些字段直接发给前端会被用户恶意使用,导致安全隐患.有些字段(如日志字段,update_time,内部状态等等)对前端并无必要,过滤这些可以减少网络数据量,提高性能

方案一:手动赋值

  • 手动创建VO对象,并逐字赋值

List<StudentVo> studentVos = new ArrayList<>();
for (Student s : students) {StudentVo vo = new StudentVo();vo.setName(s.getName());vo.setClassId(s.getClassId());// 其它字段也需手动赋值studentVos.add(vo);
}

  • 优点:可控,不存在反射性能开销

  • 缺点:当字段过多时,代码冗长,维护成本高,若实体类改变,需要改变多个地方

方案二:BeanUtils.copyProperties

  • 实现方法:利用反射机制自动复制同名属性

List<StudentVo> studentVos = new ArrayList<>();
for (Student s : students) {StudentVo vo = new StudentVo();BeanUtils.copyProperties(student, vo);studentVos.add(vo);
}

  • 优点:代码简洁,快速复制

  • 缺点:反射操作性能慢,约为手动复制的10倍,缺乏灵活性

方案三:MapStruct 推荐

  • 导入MapStruct依赖

<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.4.2.Final</version>
</dependency>
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.4.2.Final</version>
</dependency>

  • 建一个专门用于映射的文件夹mapping,编写映射接口,利用MapStruct在编译阶段自动生成高效映射代码

@Mapper//注意mapper注解不要引错了,要引入mapstruct包下的
public interface StudentMapping {StudentMapping INSTANCE = Mappers.getMapper(StudentMapping.class);StudentVo toStudentVo(Student student);List<StudentVo> toStudentVoList(List<Student> list);
}

//使用方法如下:
List<StudentVo> vos = StudentMapping.INSTANCE.toStudentVoList(students);

  • 优点:性能高,生成的代码类似于手动赋值,运行时没有反射开销,灵活性高

联表分页查询

  • 假设需要查询主表数据(如商品),及其关联的子表数据(如评论),支持分页和条件过滤.以商品(主表)和评论(子表)为例

集中式

  • 核心逻辑是提供JOIN查询主表和子数据,在单次SQL中完成所有数据的获取

  • 代码实例

    mapper.xml

<!-- 商品和评论联表查询 -->
<select id="selectProductWithComments" resultMap="productWithCommentsMap">SELECT p.id, p.name, p.price,c.id AS comment_id,c.content,c.user_idFROM product pLEFT JOIN comment c ON p.id = c.product_id${ew.customSqlSegment}  <!-- 动态条件 -->
</select><!-- 结果映射 -->
<resultMap id="productWithCommentsMap" type="ProductVO"><id property="id" column="id"/><result property="name" column="name"/><result property="price" column="price"/><collection property="comments" ofType="Comment"><id property="id" column="comment_id"/><result property="content" column="content"/><result property="userId" column="user_id"/></collection>
</resultMap>

核心点:

  • 使用处理一对多的关系,将子表数据映射为集合

  • ${ew.customSqlSegment}

    其是MP中用于动态拼接的特殊占位符,将QueryWrapperLambdaQueryWrapper中定义的查询条件如(eq,like,between),转换为合法的Sql片段,并插入到XML映射文件的SQL语句中

    mapper接口定义

// 方法参数中必须声明 @Param(Constants.WRAPPER)
Page<ProductVO> selectPage(@Param("page") Page<ProductVO> page, @Param(Constants.WRAPPER) Wrapper<ProductVO> wrapper // 关键参数
);

  • XML的使用

<select id="selectPage" resultMap="productMap">SELECT * FROM product${ew.customSqlSegment}  <!-- 动态插入 WHERE 条件 -->
</select>

  • 核心机制ew是Wrapper的别名,对应Mapper接口方法中的@Param(Constans.WRAPPER)参数当调用wrapper.eq(”name”,”张三”)时,会自动赋值为WHERE name= ‘张三’如WHERE name = '手机'需直接拼接,不能作为预编译参数

分布式(嵌套查询)

  • 分为两次查询:1.分页查询主表()商品表,2.子查询:根据主表id批量查询关联的子表数据(评论表)

  • 代码实例

<!-- 主查询 -->
<select id="selectProductPage" resultMap="productPageMap">SELECT id, name, price FROM product${ew.customSqlSegment}  <!-- 动态条件 -->
</select><!-- 嵌套子查询 根据商品ID查评论 -->
<select id="selectCommentsByProductIds" resultType="Comment">SELECT id, content, user_id, product_id FROM comment WHERE product_id IN <foreach collection="productIds" item="id" open="(" separator="," close=")">#{id}</foreach>
</select><!-- 结果映射 -->
<resultMap id="productPageMap" type="ProductVO"><id property="id" column="id"/><result property="name" column="name"/><result property="price" column="price"/><collection property="comments" ofType="Comment"select="selectCommentsByProductIds"  <!-- 关联子查询方法 -->column="{productIds=id}"             <!-- 传递参数 -->/>
</resultMap>

字段填充

  • 再更新或者新增行时,通常需要添加一些属性如创建时间,更新时间,操作人员,MP提供了一种方法自动化处理填充

代码层面的实现

  • 再实体类中标记需要填充的字段

a. 使用@TableFiled主键的fill属性指定填充策略

@Data
public class Orders implements Serializable {private static final long serialVersionUID = -29854105041572661L;@TableId(type = IdType.ASSIGN_ID)private Long orderId;private String orderNum;private Integer userId;@TableField(fill = FieldFill.INSERT)private Date orderTime;/*** 创建者*/@TableField(fill = FieldFill.INSERT)private String createBy;/*** 创建时间*/@TableField(fill = FieldFill.INSERT)private Date createTime;/*** 更新者*/@TableField(fill = FieldFill.INSERT_UPDATE)private String updateBy;/*** 更新时间*/@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;/*** 备注*/private String remark;}

b. 实现MetaObjectHandler接口

@Slf4j
@Component
public class FieldHandler implements MetaObjectHandler {// 在插入数据时,自动填充createTime和createBy字段@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill...");// 设置createTime字段的值为当前时间this.setFieldValByName("createTime", new Date(), metaObject);// 设置createBy字段的值为adminthis.setFieldValByName("createBy", "admin", metaObject);// 设置orderTime字段的值为当前时间this.setFieldValByName("orderTime", new Date(), metaObject);// 设置updateTime字段的值为当前时间this.setFieldValByName("updateTime", new Date(), metaObject);// 设置updateBy字段的值为adminthis.setFieldValByName("updateBy", "admin", metaObject);}// 在更新数据时,自动填充updateTime和updateBy字段@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill...");// 设置updateTime字段的值为当前时间this.setFieldValByName("updateTime", new Date(), metaObject);// 设置updateBy字段的值为adminthis.setFieldValByName("updateBy", "admin", metaObject);}
}

逻辑删除

  • 数据“删除”后仍保留在数据库中,通过标记is_deleted字段过滤,在实体类中使用 @TableLogic 注解

  • 避免误删导致数据永久丢失,防止删除主表数据后,关联的子表数据失效(如用户删除后,历史订单需保留)

public class User {@TableLogicprivate Integer deleted; // 1 表示删除,0 表示未删除
}

  • 当执行删除操作时,实际是在执行update操作

userMapper.deleteById(1); 
//实际执行UPDATE user SET is_deleted = 1 WHERE id = 1;

  • 查询操作通过is_deteted过滤

List<User> list = userMapper.selectList(null);
//实际执行
SELECT * FROM user WHERE is_deleted = 0;

乐观锁

  • 通过版本号(如Vesion字段)或时间戳,再数据提交时检查是否发生并非冲突,若冲突则拒绝操作,提示重试或回滚,先操作,提交时再检查冲突,使用于低并发

MP实现乐观锁

  • 在实体类中添加版本号,并使用@Version注解标记

public class Product {private Long id;private String name;@Version  // 版本号字段(MP自动管理)private Integer version;
}

  • 在配置类中添加乐观锁插件

@EnableTransactionManagement
public class MPConfig {// 创建MybatisPlusInterceptor对象@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

当存在多线程的修改操作时,MP会通过SQL语句检查version版本是否一致,如查询商品时version为1,提交完修改时MP执行UPDATE product SET name='新名字', version=2 WHERE id=1 AND version=1;,若存在另一个线程抢先修改,则version变为2,你的更新就会失效

文章转载自: ihave2carryon

原文链接:Mybatis-Plus知识点详解 - ihav2carryon - 博客园

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

相关文章:

Mybatis-Plus知识点详解

Mybatis-plus(简称MP),基于Mybatis的增强工具,保留了Mybatis的所有功能,同时增加了通用的CRUD,条件构造器,分页插件等等实用工具 特性 即拿即用:通过通用Mapper和Service,无需编写XML既可以完成单表CURE操作 Lambda支持:使用Lambda表达式构建查询条件,避免硬编码字段名,提升代…...

紧凑交叉引用表

嗯&#xff0c;用户问的是“compact xref table”&#xff0c;也就是紧凑型交叉引用表。我之前在回答中提到过交叉引用流&#xff08;XRef Stream&#xff09;&#xff0c;但可能需要更详细地解释两者的区别和联系。根据搜索结果中的网页1&#xff0c;传统的Xref表以文本形式存…...

CMake 详解:跨平台构建系统的入门与进阶

目录 一、相关知识点 1. 什么是cmake&#xff0c;为什么使用&#xff1f; 2. 构建过程 二、CMake使用流程 1. 创建 CMakeLists.txt 文件 2. 配置构建目录 3. 运行cmake 4. 运行make编译 一、相关知识点 1. 什么是cmake&#xff0c;为什么使用&#xff1f; CMake 是一个开…...

【架构设计】学习路径

掌握前置知识后&#xff0c;学习架构设计需要从理论认知到实践落地逐步推进。以下是系统化的学习路径&#xff0c;结合具体案例与实操建议&#xff0c;帮助你快速进阶&#xff1a; 一、构建架构思维基础 1. 理解架构设计的核心目标 关键问题驱动设计&#xff1a; 每个架构决策…...

14、Python 枚举与类型注解进阶

Python 枚举与类型注解进阶 文章概述 本文深入探讨Python中枚举&#xff08;Enum&#xff09;与类型注解的高级应用场景。通过剖析Enum类的核心特性、dataclass装饰器的工程实践、静态类型检查工具mypy的集成使用&#xff0c;结合状态机等实际案例&#xff0c;系统性地提升代…...

C语言 【实现电脑关机小游戏】非常好玩

引言 在时间限制内做出正确的回答&#xff0c;时间一到&#xff0c;电脑自动关机&#xff0c;听起来是不是很有意思&#xff0c;下面来看看怎么实现吧。 注意&#xff1a;该游戏只在windows系统下可以玩&#xff0c; 一、游戏原理&#xff1a; 在Windows系统下&#xff0c;通…...

【蓝桥杯速成】| 11.回溯 之 子集问题

题目一&#xff1a;子集 问题描述 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例…...

统计矩的高阶推广:经验还是理论推导?

矩的发展既是经验总结的结果&#xff0c;也是数学理论推导的产物。研究者们在分析数据、描述物理现象的过程中&#xff0c;发现了低阶矩与日常物理概念&#xff08;如质心、惯性&#xff09;之间的紧密联系&#xff0c;而高阶矩的应用往往出现在更复杂的数学体系中&#xff0c;…...

SpringBoot2集成Elasticsearch8(使用spring-boot-starter-data-elasticsearch)

写在前面 使用spring-boot-starter-data-elasticsearch集成Elasticsearch8&#xff1f; What? 官方写的不支持啊&#xff1f;让我们来看下官方给出的版本建议。 官方地址&#xff1a; https://docs.spring.io/spring-data/elasticsearch/reference/elasticsearch/versions.…...

Postgresql源码(142)子查询提升pull_up_sublinks

1 案例 drop table t_fun01; create table t_fun01 (image_id numeric primary key, content_id varchar(50), file_code varchar(20)); create index idx3 on t_fun01(content_id); create index idx4 on t_fun01(file_code); insert into t_fun01 select t.i, t.i%10, t.i%1…...

sonar代码检测研究及平台搭建

为了实现提交代码自动检测代码缺陷&#xff0c;本文介绍了一种将jenkins与gitlab集成的自动检测机制&#xff0c;如需应用于生产级开发流程&#xff0c;可在此基础上进行功能丰富和扩展,本文仅进行了原理性搭建。 一、基础环境准备 与sonar配合使用的jenkins和gitlab基础软件…...

清华大学:DeepSeek从入门到精通系列教程1-9讲(持续更新中)|大礼包免费下载

导 读INTRODUCTION 今天分享由清华大学新闻与传播学院、人工智能学院双聘教授沈阳老师团队倾力打造的《DeepSeek从入门到精通系列教程1-9讲&#xff08;持续更新中&#xff09;》&#xff0c;包含&#xff1a;《DeepSeek&#xff1a;从入门到精通》《DeepSeek如何赋能职场应用》…...

使用Python可视化图结构:从GraphML文件生成节点关系图(lightrag 生成)

引言 在数据可视化领域&#xff0c;图结构&#xff08;Graph&#xff09;常用于展示实体间的复杂关系。例如&#xff0c;文学分析中的角色关系、社交网络中的用户互动等。本文将通过一个实际案例&#xff0c;演示如何使用 NetworkX 和 Matplotlib 从 GraphML 文件生成节点关系…...

排序复习_代码纯享

头文件 #pragma once #include<iostream> #include<vector> #include<utility> using std::vector; using std::cout; using std::cin; using std::endl; using std::swap;//插入排序 //1、直接插入排序&#xff08;稳定&#xff09; void InsertSort(vecto…...

Docker Hub Mirror 终极解决方案——0成本,超高速!

CNB Docker Mirror (cdm) CNB Docker Mirror 是一个基于 CNB 的 Docker 镜像加速工具&#xff0c;提供本地镜像加速功能。 功能特性 镜像加速&#xff1a;在本地启动连接到 CNB 环境的 Docker 镜像加速服务&#xff0c;然后通过配置 Docker 客户端实现镜像加速下载自动重连&…...

2000-2019年各省地方财政车船税数据

2000-2019年各省地方财政车船税数据 1、时间&#xff1a;2000-2019年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区、年份、地方财政车船税 4、范围&#xff1a;31省 5、指标说明&#xff1a;车船税作为地方财政的重要组成部分&#x…...

c#处理算数溢出的情况

在C#中&#xff0c;算术运算的溢出处理可以通过 checked 和 unchecked 关键字控制&#xff0c;默认行为是 静默截断&#xff08;unchecked模式&#xff09;&#xff0c;但可以通过配置或代码块显式调整。以下是详细说明&#xff1a; 1. 默认行为&#xff08;unchecked模式&…...

Java「Deque」 方法详解:从入门到实战

Java Deque 各种方法解析&#xff1a;从入门到实战 在 Java 编程中&#xff0c;Deque&#xff08;双端队列&#xff09;是一个功能强大的数据结构&#xff0c;允许开发者从队列的两端高效地添加、删除和检查元素。作为 java.util 包中的一部分&#xff0c;Deque 接口继承自 Qu…...

简记_FPGA 硬件最小系统设计

一、FPGA板级设计的五要素 1.1、电源电路 核心电压&#xff1a;一般为固定值 IO电压&#xff1a;FPGA的IO分为多个bank&#xff0c;同一个bank的不同IO引脚电压相同&#xff0c;不同bank的电压可以不同 辅助电压&#xff1a;除了核心电压和IO电压&#xff0c;FPGA工作所需的…...

C++题目

1、内存管理 1.内存模型 栈:在执行函数时&#xff0c;函数内局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结束时这些存储单元自动被释放。 堆&#xff1a;就是那些由new分配的内存块&#xff0c;其释放由程序员控制&#xff08;一个new对应一个delete&#xff09…...

Vulhub-jangow-01-1.0.1通关攻略

第0步&#xff1a; 打开靶机&#xff0c;按下shift&#xff0c;出现下图界面 在此页面按下e键&#xff0c;进入如下界面&#xff0c; 将ro 替换为 rw signie init/bin/bash 替换完毕后&#xff0c;按下Ctrl键X键&#xff0c;进入如下页面 ip a查看网卡信息 编辑配置文件网卡信…...

入剖析 Android Compose 框架的关键帧动画(keyframes、Animatable)(二十三)

深入剖析 Android Compose 框架的关键帧动画&#xff08;keyframes、Animatable&#xff09; 引言 在当今的 Android 应用开发领域&#xff0c;用户体验已成为衡量一款应用成功与否的关键因素之一。而动画作为提升用户体验的重要手段&#xff0c;能够为应用增添生动性和交互性…...

java中的枚举类型和c,c++的有区别吗?c,c++的枚举,结构体,联合体,三种数据有什么区别和联系

Java 枚举类型与 C、C 枚举类型的区别 1. 类型安全 Java&#xff1a;Java 的枚举类型是类型安全的。枚举常量是枚举类型的实例&#xff0c;编译器会严格检查传递的参数是否为该枚举类型的有效常量。例如&#xff1a; java Apply enum Color { RED, GREEN, BLUE } // 编译器会检…...

详解Redis的持久化与数据可靠性

Redis持久化与数据可靠性详解&#xff08;结合实例&#xff09; Redis作为内存数据库&#xff0c;持久化是保证数据不丢失的核心机制。它通过将内存数据保存到磁盘&#xff0c;确保服务器重启后能恢复数据。Redis提供RDB、AOF和混合持久化三种方式&#xff0c;下面通过实例和操…...

1、mysql基础篇--概述

关系型数据库&#xff08;RDBMS&#xff09; 概念特点&#xff1a;数据模型&#xff1a; 概念 建立在关系模型基础上&#xff0c;有多张表相互连接的二维表组成的数据库 特点&#xff1a; 1、使用表存储&#xff0c;格式统一&#xff0c;便于维护 2、使用sql语言操作&#…...

【Tiny RDM】Redis客户端工具

Tiny RDM Tiny RDM是一款现代化、轻量级、跨平台的Redis客户端&#xff0c;支持Mac、Windows和Linux&#xff0c;目前在Github上已有10kStar。 Github 项目地址&#xff1a; https://github.com/tiny-craft/tiny-rdm 功能特性 极度轻量&#xff0c;基于Webview2&#xff0c…...

常见框架漏洞攻略-Shiro篇

漏洞名称 Shiro rememberMe反序列化漏洞 漏洞简介 Apache Shiro是⼀个强⼤易⽤的Java安全框架&#xff0c;提供了认证、授权、加密和会话管理等功能。Shiro框架直观、易⽤&#xff0c;同时也能提供健壮的安全性。 漏洞原理 在Shiro框架下&#xff0c;⽤户登陆成功后会⽣成…...

常见框架漏洞之一:Thinkphp5x

ThinkPHP是为了简化企业级应⽤开发和敏捷WEB应⽤开发⽽诞⽣的&#xff0c;是⼀个快速、兼容⽽且简单的轻量级国产PHP开发框架&#xff0c;诞⽣于2006年初&#xff0c;原名FCS&#xff0c;2007年元旦正式更名为 ThinkPHP&#xff0c;遵循Apache2开源协议发布&#xff0c;从Stru…...

MORL4PDEs:基于多目标优化与强化学习的数据驱动偏微分方程发现

摘要&#xff1a;本文提出了一种结合多目标优化与强化学习的数据驱动方法MORL4PDEs&#xff0c;用于从复杂系统观测数据中发现简洁的偏微分方程&#xff08;PDE&#xff09;。该方法无需预定义候选函数库&#xff0c;通过神经网络代理生成符号表达式&#xff0c;结合遗传算法优…...

UniApp和微信小程序中v-switch夜间模式动画开关

UniApp兼容版 <template><view><view class"main-container" :style"{ backgroundColor: value ? #45e3f9 : #20114c,transform:scale(${size})}" tap"onClick"><view class"content" :style"{ left: val…...

六十天Linux从0到项目搭建第四天(通配符命令、其他命令、压缩解压工具、shell的感性理解、linux权限解析)

通配符&#xff08;Wildcard&#xff09; 是 Shell 提供的特殊字符&#xff0c;用于 匹配文件名或路径名&#xff0c;可以代替一个或多个字符&#xff0c;使得命令能批量操作文件&#xff0c;而无需手动输入每个文件名。 典型用法 * 匹配任意字符 *.txt → 匹配所有 .txt 文…...

RAG优化:python从零实现自适应检索增强Adaptive Retrieval

开篇:当RAG遇上“自适应大脑”,检索从此不再“一根筋”!🧠 想象一下,你的AI助手是个超级聪明的“学霸”,但有时候却像个“一根筋”的机器人——无论你问它什么,它都用同一种方式去回答。问它“什么是XAI?”它给你一堆定义;问它“AI发展太快了吗?”它还是给你一堆定…...

C语言实现的冰墩墩

在windows系统下&#xff0c;vs 2022编译。 其中#include <graphics.h>需要自己下载安装。 环境配置没什么难度&#xff0c;直接上demo。 代码如下&#xff1a; #include <graphics.h> #include <conio.h> #include <math.h> #define PI acos(-1.0…...

【构建CV图像识别系统】从传统方法到深度学习

目录 1. 图像的基本概念1.1 像素与色彩1.2 过滤与卷积 2. 图像分类与检测3. 图像特征的提取3.1 全局特征3.2 局部特征3.2.1 边缘&#xff08;Edge&#xff09;3.2.2 角点&#xff08;Corner&#xff09;3.2.3 SIFT 特征 4. 传统方法与深度学习在图像识别中的应用4.1 基于传统方…...

在Centos 7环境下安装MySQL

前言&#xff1a;在安装与卸载MySQL时&#xff0c;用户需切换为root&#xff0c;这样安装之后&#xff0c;普通用户也能够使用。 Tips:我们在刚开始学习时&#xff0c;尽量全部使用root进行&#xff0c;适应mysql语句&#xff0c;后面学了用户管理&#xff0c;就可以考虑新建普…...

【机器学习基础 4】 Pandas库

一、Pandas库简介 Pandas 是一个开源的 Python 数据分析库&#xff0c;主要用于数据清洗、处理、探索与分析。其核心数据结构是 Series&#xff08;一维数据&#xff09;和 DataFrame&#xff08;二维表格数据&#xff09;&#xff0c;可以让我们高效地操作结构化数据。Pandas …...

干部监督预警系统的定义与功能

一、干部监督预警系统是什么&#xff1f; 干部监督预警系统是通过整合多源数据&#xff08;如干部档案、履职表现、廉政记录、舆情反馈等&#xff09;&#xff0c;利用大数据分析、人工智能等技术&#xff0c;对干部行为进行实时监测、风险评估和分级预警的数字化管理工具。 二…...

可视化图解算法:链表的奇偶重排(排序链表)

1. 题目 描述 给定一个单链表&#xff0c;请设定一个函数&#xff0c;将链表的奇数位节点和偶数位节点分别放在一起&#xff0c;重排后输出。 注意是节点的编号而非节点的数值。 数据范围&#xff1a;节点数量满足 0≤n≤105&#xff0c;节点中的值都满足 0≤val≤10000 要…...

获取小红书笔记详情接口的详细指南

一、引言 小红书作为一个集社交、购物、分享于一体的综合性平台&#xff0c;拥有海量的用户和丰富的笔记内容。小红书笔记详情API接口为开发者提供了一种高效获取笔记详细信息的方法&#xff0c;包括笔记的标题、正文、图片、视频、标签、点赞数、评论数等。这些数据可以帮助开…...

麒麟系统运维指令

麒麟系统运维指令 麒麟系统运维指令1、 查看系统版本2、查看系统信息3、用户与权限管理4. 网络相关命令5. 包管理6. 文件操作7. 进程管理 麒麟系统运维指令 1、 查看系统版本 目的指令查看操作系统版本信息cat /etc/os-release查看操作系统版本信息hostnamectl查看内核版本un…...

pyqt SQL Server 数据库查询

一、概述 本项目旨在开发一个基于 Python 和 PyQt6 的数据库查询工具&#xff0c;该工具能够连接到 SQL Server 数据库&#xff0c;显示数据库中的表名&#xff0c;支持用户输入 SQL 查询语句进行数据查询&#xff0c;并将查询结果展示在表格中。同时&#xff0c;为了提升用户…...

抓包软件【Fiddler】

我叫补三补四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲Fiddler 什么是Fidder Fiddler是一款非常流行并且实用的HTTP抓包工具&#xff0c;原理是在电脑上开启一个HTTP代理服务器&#xff0c;然后转发所有的HTTP请求和响应。是用C#开发的工具…...

SpringCould微服务架构之Docker(1)

项目中微服务比较多的时候&#xff0c;一个一个手动的部署太麻烦了&#xff0c;所以就需要用到Docker。 项目部署中的问题&#xff1a; Docker是一种快速交付应用、运行应用的技术。...

计算图(Computation Graph)

在强化学习中&#xff0c;TensorFlow的计算图&#xff08;Computation Graph&#xff09;是用于描述模型结构和训练流程的核心机制。 1. 计算图的基本概念 定义&#xff1a;计算图是TensorFlow中表示数学运算和数据流动的有向图。图中的节点&#xff08;Nodes&#xff09;代表…...

邮件营销:如何设置合适的发送频率

在邮件营销里&#xff0c;把握好发送频率特别关键&#xff0c;这直接关系到客户愿不愿意搭理你的邮件&#xff0c;以及邮件营销能不能达到预期效果。下面这几个步骤和建议&#xff0c;能帮你找到合适的邮件发送频率&#xff1a; 一、了解目标受众 分析客户行为&#xff1a;查…...

React项目中,递归写法获取tree的id集合

后端接口返回一个childrens的树&#xff0c;最后要拿到的是每个childrens下第一个对象的id集合&#xff0c;用于编辑页的回显 采用的是递归写法&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; const categoryIds: Array&…...

深入解析Linux网络、安全与容器技术

1. Netfilter&#xff1a;Linux内核的包处理框架 Netfilter 是Linux内核中用于控制网络数据包的核心机制&#xff0c;负责处理数据包的过滤、修改和转发。其核心功能包括&#xff1a; 包过滤&#xff08;Packet Filtering&#xff09;&#xff1a;根据规则允许或拒绝数据包通过…...

AF3 Rotation 类解读

Rotation 类(rigid_utils 模块)是 AlphaFold3 中用于 3D旋转 的核心组件,支持两种旋转表示: 1️⃣ 旋转矩阵 (3x3) 2️⃣ 四元数 (quaternion, 4元向量) 👉 设计目标: 允许灵活选择 旋转矩阵 或 四元数 封装了常用的 旋转操作(组合、逆旋转、应用到点上等) 像 torch.…...

数据预处理习题

简述常用的文本数据类型。 结构化文本&#xff1a;如数据库中的表格数据、JSON/XML格式数据&#xff0c;具有明确的字段和层级关系。非结构化文本&#xff1a;如自然语言文本&#xff08;新闻、社交媒体内容&#xff09;、长文档&#xff08;书籍、论文&#xff09;&#xff0…...

常见框架漏洞—中间件IIS

一.IIS6.x篇 1.在Windows server 2003中搭建网站 2.访问网站&#xff0c;并对该网站进行抓包 3.修改提交方式为PUT&#xff0c;然后写入木马 4.修改提交方式为MOVE&#xff0c;令将其更名为脚本⽂档后缀 5.我们在Windows server 2003中可以看到我们上传的shell.asp 6.我们在网…...