装饰器模式与模板方法模式实现MyBatis-Plus QueryWrapper 扩展
pom
<dependency><groupId>com.github.yulichang</groupId><artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 -->
</dependency>
MPJLambdaWrapperX
/*** 拓展 MyBatis Plus Join QueryWrapper 类,主要增加如下功能:* <p>* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。** @param <T> 数据类型*/
public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {public MPJLambdaWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {MPJWrappers.lambdaJoin().like(column, val);if (StringUtils.hasText(val)) {return (MPJLambdaWrapperX<T>) super.like(column, val);}return this;}public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {return (MPJLambdaWrapperX<T>) super.in(column, values);}return this;}public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {return (MPJLambdaWrapperX<T>) super.in(column, values);}return this;}public MPJLambdaWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {if (ObjectUtil.isNotEmpty(val)) {return (MPJLambdaWrapperX<T>) super.eq(column, val);}return this;}public MPJLambdaWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {if (ObjectUtil.isNotEmpty(val)) {return (MPJLambdaWrapperX<T>) super.ne(column, val);}return this;}public MPJLambdaWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (MPJLambdaWrapperX<T>) super.gt(column, val);}return this;}public MPJLambdaWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (MPJLambdaWrapperX<T>) super.ge(column, val);}return this;}public MPJLambdaWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (MPJLambdaWrapperX<T>) super.lt(column, val);}return this;}public MPJLambdaWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (MPJLambdaWrapperX<T>) super.le(column, val);}return this;}public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {if (val1 != null && val2 != null) {return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);}if (val1 != null) {return (MPJLambdaWrapperX<T>) ge(column, val1);}if (val2 != null) {return (MPJLambdaWrapperX<T>) le(column, val2);}return this;}public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {Object val1 = ArrayUtils.get(values, 0);Object val2 = ArrayUtils.get(values, 1);return betweenIfPresent(column, val1, val2);}// ========== 重写父类方法,方便链式调用 ==========@Overridepublic <X> MPJLambdaWrapperX<T> eq(boolean condition, SFunction<X, ?> column, Object val) {super.eq(condition, column, val);return this;}@Overridepublic <X> MPJLambdaWrapperX<T> eq(SFunction<X, ?> column, Object val) {super.eq(column, val);return this;}@Overridepublic <X> MPJLambdaWrapperX<T> orderByDesc(SFunction<X, ?> column) {//noinspection uncheckedsuper.orderByDesc(true, column);return this;}@Overridepublic MPJLambdaWrapperX<T> last(String lastSql) {super.last(lastSql);return this;}@Overridepublic <X> MPJLambdaWrapperX<T> in(SFunction<X, ?> column, Collection<?> coll) {super.in(column, coll);return this;}@Overridepublic MPJLambdaWrapperX<T> selectAll(Class<?> clazz) {super.selectAll(clazz);return this;}@Overridepublic MPJLambdaWrapperX<T> selectAll(Class<?> clazz, String prefix) {super.selectAll(clazz, prefix);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectAs(SFunction<S, ?> column, String alias) {super.selectAs(column, alias);return this;}@Overridepublic <E> MPJLambdaWrapperX<T> selectAs(String column, SFunction<E, ?> alias) {super.selectAs(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectAs(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectAs(column, alias);return this;}@Overridepublic <E, X> MPJLambdaWrapperX<T> selectAs(String index, SFunction<E, ?> column, SFunction<X, ?> alias) {super.selectAs(index, column, alias);return this;}@Overridepublic <E> MPJLambdaWrapperX<T> selectAsClass(Class<E> source, Class<?> tag) {super.selectAsClass(source, tag);return this;}@Overridepublic <E, F> MPJLambdaWrapperX<T> selectSub(Class<E> clazz, Consumer<MPJLambdaWrapper<E>> consumer, SFunction<F, ?> alias) {super.selectSub(clazz, consumer, alias);return this;}@Overridepublic <E, F> MPJLambdaWrapperX<T> selectSub(Class<E> clazz, String st, Consumer<MPJLambdaWrapper<E>> consumer, SFunction<F, ?> alias) {super.selectSub(clazz, st, consumer, alias);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column) {super.selectCount(column);return this;}@Overridepublic MPJLambdaWrapperX<T> selectCount(Object column, String alias) {super.selectCount(column, alias);return this;}@Overridepublic <X> MPJLambdaWrapperX<T> selectCount(Object column, SFunction<X, ?> alias) {super.selectCount(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column, String alias) {super.selectCount(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectCount(column, alias);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column) {super.selectSum(column);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column, String alias) {super.selectSum(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectSum(column, alias);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column) {super.selectMax(column);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column, String alias) {super.selectMax(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectMax(column, alias);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column) {super.selectMin(column);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column, String alias) {super.selectMin(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectMin(column, alias);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column) {super.selectAvg(column);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column, String alias) {super.selectAvg(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectAvg(column, alias);return this;}@Overridepublic <S> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column) {super.selectLen(column);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column, String alias) {super.selectLen(column, alias);return this;}@Overridepublic <S, X> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column, SFunction<X, ?> alias) {super.selectLen(column, alias);return this;}}
LambdaQueryWrapperX
/*** 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:* <p>* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。** @param <T> 数据类型*/
public class LambdaQueryWrapperX<T> extends LambdaQueryWrapper<T> {public LambdaQueryWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {if (StringUtils.hasText(val)) {return (LambdaQueryWrapperX<T>) super.like(column, val);}return this;}public LambdaQueryWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {return (LambdaQueryWrapperX<T>) super.in(column, values);}return this;}public LambdaQueryWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {return (LambdaQueryWrapperX<T>) super.in(column, values);}return this;}public LambdaQueryWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {if (ObjectUtil.isNotEmpty(val)) {return (LambdaQueryWrapperX<T>) super.eq(column, val);}return this;}public LambdaQueryWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {if (ObjectUtil.isNotEmpty(val)) {return (LambdaQueryWrapperX<T>) super.ne(column, val);}return this;}public LambdaQueryWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (LambdaQueryWrapperX<T>) super.gt(column, val);}return this;}public LambdaQueryWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (LambdaQueryWrapperX<T>) super.ge(column, val);}return this;}public LambdaQueryWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (LambdaQueryWrapperX<T>) super.lt(column, val);}return this;}public LambdaQueryWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {if (val != null) {return (LambdaQueryWrapperX<T>) super.le(column, val);}return this;}public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {if (val1 != null && val2 != null) {return (LambdaQueryWrapperX<T>) super.between(column, val1, val2);}if (val1 != null) {return (LambdaQueryWrapperX<T>) ge(column, val1);}if (val2 != null) {return (LambdaQueryWrapperX<T>) le(column, val2);}return this;}public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {Object val1 = ArrayUtils.get(values, 0);Object val2 = ArrayUtils.get(values, 1);return betweenIfPresent(column, val1, val2);}// ========== 重写父类方法,方便链式调用 ==========@Overridepublic LambdaQueryWrapperX<T> eq(boolean condition, SFunction<T, ?> column, Object val) {super.eq(condition, column, val);return this;}@Overridepublic LambdaQueryWrapperX<T> eq(SFunction<T, ?> column, Object val) {super.eq(column, val);return this;}@Overridepublic LambdaQueryWrapperX<T> orderByDesc(SFunction<T, ?> column) {super.orderByDesc(true, column);return this;}@Overridepublic LambdaQueryWrapperX<T> last(String lastSql) {super.last(lastSql);return this;}@Overridepublic LambdaQueryWrapperX<T> in(SFunction<T, ?> column, Collection<?> coll) {super.in(column, coll);return this;}
}
QueryWrapperX
/*** 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:** 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。** @param <T> 数据类型*/
public class QueryWrapperX<T> extends QueryWrapper<T> {public QueryWrapperX<T> likeIfPresent(String column, String val) {if (StringUtils.hasText(val)) {return (QueryWrapperX<T>) super.like(column, val);}return this;}public QueryWrapperX<T> inIfPresent(String column, Collection<?> values) {if (!CollectionUtils.isEmpty(values)) {return (QueryWrapperX<T>) super.in(column, values);}return this;}public QueryWrapperX<T> inIfPresent(String column, Object... values) {if (!ArrayUtils.isEmpty(values)) {return (QueryWrapperX<T>) super.in(column, values);}return this;}public QueryWrapperX<T> eqIfPresent(String column, Object val) {if (val != null) {return (QueryWrapperX<T>) super.eq(column, val);}return this;}public QueryWrapperX<T> neIfPresent(String column, Object val) {if (val != null) {return (QueryWrapperX<T>) super.ne(column, val);}return this;}public QueryWrapperX<T> gtIfPresent(String column, Object val) {if (val != null) {return (QueryWrapperX<T>) super.gt(column, val);}return this;}public QueryWrapperX<T> geIfPresent(String column, Object val) {if (val != null) {return (QueryWrapperX<T>) super.ge(column, val);}return this;}public QueryWrapperX<T> ltIfPresent(String column, Object val) {if (val != null) {return (QueryWrapperX<T>) super.lt(column, val);}return this;}public QueryWrapperX<T> leIfPresent(String column, Object val) {if (val != null) {return (QueryWrapperX<T>) super.le(column, val);}return this;}public QueryWrapperX<T> betweenIfPresent(String column, Object val1, Object val2) {if (val1 != null && val2 != null) {return (QueryWrapperX<T>) super.between(column, val1, val2);}if (val1 != null) {return (QueryWrapperX<T>) ge(column, val1);}if (val2 != null) {return (QueryWrapperX<T>) le(column, val2);}return this;}public QueryWrapperX<T> betweenIfPresent(String column, Object[] values) {if (values!= null && values.length != 0 && values[0] != null && values[1] != null) {return (QueryWrapperX<T>) super.between(column, values[0], values[1]);}if (values!= null && values.length != 0 && values[0] != null) {return (QueryWrapperX<T>) ge(column, values[0]);}if (values!= null && values.length != 0 && values[1] != null) {return (QueryWrapperX<T>) le(column, values[1]);}return this;}// ========== 重写父类方法,方便链式调用 ==========@Overridepublic QueryWrapperX<T> eq(boolean condition, String column, Object val) {super.eq(condition, column, val);return this;}@Overridepublic QueryWrapperX<T> eq(String column, Object val) {super.eq(column, val);return this;}@Overridepublic QueryWrapperX<T> orderByDesc(String column) {super.orderByDesc(true, column);return this;}@Overridepublic QueryWrapperX<T> last(String lastSql) {super.last(lastSql);return this;}@Overridepublic QueryWrapperX<T> in(String column, Collection<?> coll) {super.in(column, coll);return this;}
}
一、核心作用
1. 联表查询支持
- 避免空值条件拼接:自动跳过值为空的查询条件,防止生成 WHERE column = null 的低效 SQL
- MyBatis-Plus Join 扩展:提供基于 Lambda 的联表查询能力,弥补 MyBatis Plus 原生不支持联表的缺陷。
- 类型安全:通过 SFunction<T, ?> 泛型 Lambda 表达式引用实体字段,避免硬编码字段名。
2. 链式 API 设计
// 示例:联表查询用户和部门信息
new MPJLambdaWrapper<UserDO>().selectAll(UserDO.class).select(DepartmentDO::getName, "deptName").leftJoin(DepartmentDO.class, DepartmentDO::getId, UserDO::getDeptId).eq(UserDO::getStatus, 0);
二、扩展点
1. 条件空值安全(核心增强)
通过 xxxIfPresent 方法实现 空值自动跳过,避免无效条件拼接。
| 方法 | 作用 | 示例代码 |
|---|---|---|
| eqIfPresent | 值非空时添加 eq 条件 | wrapper.eqIfPresent(UserDO::getName, name) |
| inIfPresent | 集合非空时添加 in 条件 | wrapper.inIfPresent(UserDO::getRoleIds, roleIds) |
| betweenIfPresent | 区间值有效时添加 between 条件 | wrapper.betweenIfPresent(UserDO::getCreateTime, start, end) |
2. 链式调用增强
重写父类方法(如 eq, select)返回子类类型,保持链式调用连贯性:
public MPJLambdaWrapperX<T> eq(SFunction<X, ?> column, Object val) {super.eq(column, val);return this; // 返回 MPJLambdaWrapperX 类型而非父类
}
@Override
public LambdaQueryWrapperX<T> eq(SFunction<T, ?> column, Object val) {super.eq(column, val);return this;
}
3. 智能区间处理
betweenIfPresent 方法支持 单边区间 自动转换:
// 当 val2 为空时,转换为 ge 条件
wrapper.betweenIfPresent(UserDO::getCreateTime, startTime, null);
// 生成 SQL:WHERE create_time >= startTime
三、设计模式分析
1. 装饰器模式(Decorator Pattern)
- 表现:MPJLambdaWrapperX 在 MPJLambdaWrapper 基础上增强功能(如空值安全),而非直接修改父类。
- 优势:符合开闭原则,MyBatis-Plus Join 升级时只需调整父类引用。
2. 模板方法模式(Template Method Pattern)
- 表现:xxxIfPresent 方法封装了空值判断逻辑,子类只需调用父类条件方法。
public MPJLambdaWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {if (ObjectUtil.isNotEmpty(val)) {return (MPJLambdaWrapperX<T>) super.eq(column, val); // 调用父类方法}return this;
}public LambdaQueryWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {if (ObjectUtil.isNotEmpty(val)) {return (LambdaQueryWrapperX<T>) super.eq(column, val); // 调用父类方法}return this;
}
四、典型使用场景
1. 动态查询条件构建
public List<UserDO> getUsers(String name, Integer status, LocalDateTime startTime) {return joinMapper.selectJoinList(new MPJLambdaWrapperX<UserDO>().eqIfPresent(UserDO::getName, name) // name 为空时不拼接.eqIfPresent(UserDO::getStatus, status) // status 为空时不拼接.geIfPresent(UserDO::getCreateTime, startTime).leftJoin(DepartmentDO.class, ...));
}
2. 复杂联表查询
wrapper.selectAll(UserDO.class).selectAs(DepartmentDO::getName, UserRespVO::getDeptName).leftJoin(DepartmentDO.class, DepartmentDO::getId, UserDO::getDeptId).inIfPresent(UserDO::getRoleIds, roleIds);
3. 区间查询优化
// 处理可能不完整的区间参数
wrapper.betweenIfPresent(UserDO::getCreateTime, params.getStartTime(), params.getEndTime());
五、与原生 MyBatis Plus 对比
| 特性 | MyBatis Plus QueryWrapper | QueryWrapperX | MPJLambdaWrapperX | MyBatis Plus LambdaQueryWrapper | LambdaQueryWrapperX |
|---|---|---|---|---|---|
| 联表支持 | 不支持 | 不支持 | 支持 LEFT/INNER JOIN | 不支持 | 不支持 |
| 字段引用 | 字符串字段名(如 “name”) | 字符串字段名(如 “name”) | Lambda 表达式(如 UserDO::getName) | Lambda 表达式(如 UserDO::getName) | Lambda 表达式(如 UserDO::getName) |
| 空值处理 | 需手动判空 | 内置 xxxIfPresent 方法 | 内置 xxxIfPresent 方法自动处理 | 内置 xxxIfPresent 方法自动处理 | 内置 xxxIfPresent 方法自动处理 |
| 类型安全 | 容易拼写错误 | 容易拼写错误 | 编译期检查字段是否存在 | 编译期检查字段是否存在 | 编译期检查字段是否存在 |
相关文章:
装饰器模式与模板方法模式实现MyBatis-Plus QueryWrapper 扩展
pom <dependency><groupId>com.github.yulichang</groupId><artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 --> </dependency>MPJLambdaWrapperX /*** 拓展 MyBatis Plus Join QueryWrapper 类&…...
【PCIE711-214】基于PCIe总线架构的4路HD-SDI/3G-SDI视频图像模拟源
产品概述 PCIE711-214是一款基于PCIE总线架构的4路SDI视频模拟源。该板卡为标准的PCIE插卡,全高尺寸,适合与PCIE总线的工控机或者服务器,板载协议处理器,可以通过PCIE总线将上位机的YUV 422格式视频数据下发通过SDI接口播放出去&…...
突破反爬困境:SDK开发,浏览器模块(七)
声明 本文所讨论的内容及技术均纯属学术交流与技术研究目的,旨在探讨和总结互联网数据流动、前后端技术架构及安全防御中的技术演进。文中提及的各类技术手段和策略均仅供技术人员在合法与合规的前提下进行研究、学习与防御测试之用。 作者不支持亦不鼓励任何未经授…...
rce操作
Linux命令长度突破限制 源码 <?php $param $_REQUEST[param];if ( strlen($param) < 8 ) {echo shell_exec($param); } echo执行函数,$_REQUEST可以接post、get、cookie传参 源码中对参数长度做了限制,小于8位,可以利用临时函数&…...
LabVIEW高效溢流阀测试系统
开发了一种基于LabVIEW软件和PLC硬件的溢流阀测试系统。通过集成神经网络优化的自适应PID控制器,该系统能自动进行压力稳定性、寿命以及动静态性能测试。该设计不仅提升了测试效率,还通过智能化控制提高了数据的精确性和操作的便捷性。 项目背景&…...
Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明,包含代码示例和关键要点
以下是 Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明,包含代码示例和关键要点: 一、JdbcTemplate 处理枚举类型转换 1. 场景说明 假设数据库存储的是枚举的 String 或 int 值,但 Java 实体类使用 enu…...
DataGear 5.3.0 制作支持导出表格数据的数据可视化看板
DataGear 内置表格图表底层采用的是DataTable表格组件,默认并未引入导出数据的JS支持库,如果有导出表格数据需求,则可以在看板中引入导出相关JS支持库,制作具有导出CSV、Excel、PDF功能的表格数据看板。 在新发布的5.3.0版本中&a…...
Web网页内嵌 Adobe Pdf Reader 谷歌Chrome在线预览编辑PDF文档
随着数字化办公的普及,PDF文档已成为信息处理的核心载体,虽然桌面端有很多软件可以实现预览编辑PDF文档,而在线在线预览编辑PDF也日益成为一个难题。 作为网页内嵌本地程序的佼佼者——猿大师中间件,之前发布的猿大师办公助手&am…...
歌词json
绽放(4:17) {"lyrics": [{time: 00:00, text: 作词:郑润泽},{time: 00:01, text: 作曲:郑润泽},{time: 00:02, text: 编曲:赵建飞},{time: 00:03, text: 制作人:李淘/赵建飞},{time: 00:09, tex…...
CNG汽车加气站操作工备考真题及答案解析【判断题】
1、燃气经营许可证按照燃气经营规模和类别实行分级审批。(√) 解析:不同规模和类别的燃气经营,其许可证审批级别不同,以确保经营活动的规范和安全。 2、依照《安全生产法》的规定,安全生产监督检查人员对检…...
Sentinel[超详细讲解]-1
定义一系列 规则 👺,对资源进行 保护 👺, 如果违反的了规则,则抛出异常,看是否有fallback兜底处理,如果没有则直接返回异常信息😎 1. 快速入门 1.1 引入 Sentinel 依赖 <depend…...
CUDA专题8—CUDA L2缓存完全指南:从持久化策略到性能优化实战
1. 设备内存L2缓存访问管理 当CUDA内核反复访问全局内存中的某个数据区域时,此类数据访问可视为持久化(persisting)访问。反之,若数据仅被访问一次,则可视为流式(streaming)访问。 从CUDA 11.0开始,计算能力8.0及以上的设备能够调控L2缓存中数据的持久性,从而可能实现更…...
如何让 SQL2API 进化为 Text2API:自然语言生成 API 的深度解析?
在过去的十年里,技术的进步日新月异,尤其是在自动化、人工智能与自然语言处理(NLP)方面。 随着“低代码”平台的崛起,开发者和非技术人员能够更轻松地构建强大而复杂的应用程序。然而,尽管技术门槛降低了&…...
OCCT(2)Windows平台编译OCCT
文章目录 一、Windows平台编译OCCT1、准备环境2、下载源码3、下载第三方库4、使用 CMake 配置5、编译OCCT源码6、运行示例 一、Windows平台编译OCCT 1、准备环境 安装工具: Visual Studio(推荐 VS2019/2022,选择 C 桌面开发 组件࿰…...
【蓝桥杯—单片机】通信总线专项 | 真题整理、解析与拓展 (更新ing...)
通信总线专项 前言SPI第十五届省赛题 UART/RS485/RS232UARTRS485RS232第十三届省赛题小结和拓展:传输方式的分类第十三届省赛 其他相关考点网络传输速率第十五届省赛题第十二届省赛题 前言 在本文中我会把 蓝桥杯单片机赛道 历年真题 中涉及到通信总线的题目整理出…...
【Golang】泛型与类型约束
文章目录 一、环境二、没有泛型的Go三、泛型的优点四、理解泛型(一)定义(二)调用(三)类型约束(Type Constraint)1)接口与约束2)结构体类型约束3)类…...
Uni-app页面信息与元素影响解析
获取窗口信息uni.getWindowInfo {pixelRatio: 3safeArea:{bottom: 778height: 731left: 0right: 375top: 47width: 375}safeAreaInsets: {top: 47, left: 0, right: 0, bottom: 34},screenHeight: 812,screenTop: 0,screenWidth: 375,statusBarHeight: 47,windowBottom: 0,win…...
CentOS(最小化)安装之后,快速搭建Docker环境
本文以VMware虚拟机中安装最小化centos完成后开始。 1. 检查网络 打开网卡/启用网卡 执行命令ip a查看当前的网络连接是否正常: 如果得到的结果和我一样,有ens网卡但是没有ip地址,说明网卡未打开 手动启用: nmcli device sta…...
【身份证证件OCR识别】批量OCR识别身份证照片复印件图片里的文字信息保存表格或改名字,基于QT和腾讯云api_ocr的实现方式
项目背景 在许多业务场景中,需要处理大量身份证照片复印件,手动输入其中的文字信息效率低下且容易出错。利用 OCR(光学字符识别)技术可以自动识别身份证图片中的文字信息,结合 QT 构建图形用户界面,方便用户操作,同时使用腾讯 OCR API 能够保证较高的识别准确率。 界面…...
IP属地和发作品的地址不一样吗
在当今这个数字化时代,互联网已经成为人们日常生活不可或缺的一部分。随着各大社交平台功能的不断完善,一个新功能——IP属地显示,逐渐走进大众视野。这一功能在微博、抖音、快手等各大平台上得到广泛应用,旨在帮助公众识别虚假信…...
Redis - 概述
目录 编辑 一、什么是redis 二、redis能做什么(有什么特点)? 三、redis有什么优势 四、Redis与其他key-value存储有什么不同 五、Redis命令 六、Redis数据结构 1、基础数据结构 2、高级数据结构 一、什么是redis 1、redis&#x…...
vue3 根据城市名称计算城市之间的距离
<template><div class"distance-calculator"><h1>城市距离计算器</h1><!-- 城市输入框 --><div class"input-group"><inputv-model"city1"placeholder"请输入第一个城市"keyup.enter"cal…...
html 列表循环滚动,动态初始化字段数据
html <div class"layui-row"><div class"layui-col-md4"><div class"boxall"><div class"alltitle">超时菜品排行</div><div class"marquee-container"><div class"scroll-…...
QT基础:安装与简介
QT初级 1、简介1.1 安装1.2 设置1.3 在VS中配置Qt1.3 帮助文档 2、Qt项目2.1 创建项目2.1 项目文件2.2 Qt中的窗口类窗口显示 2.3 坐标体系2.4 内存回收 1、简介 QT是一个跨平台的C应用程序开发框架。几乎支持所有的平台, 可用于桌面程序开发以及嵌入式开发。 Qt是标准 C 的扩…...
41、当你在 index.html 中引用了一个公共文件(比如 common.js),修改这个文件后,用户访问页面时仍然看到旧内容,因为浏览器缓存了旧版本
由于浏览器缓存导致公共文件无法更新。当用户修改了公共文件(如 JavaScript 或 CSS),但 index.html 中引用的文件名没有变化,浏览器会认为文件没有更新,继续使用缓存的旧版本。因此,需要通过某种方式让浏览…...
WEB安全-HTTPS
1 需求 结合Wireshark抓包实战,图文详解TCP三次握手及四次挥手原理(附下载) 结合Wireshark抓包分析,沉浸式体验HTTP请求的一次完整交互过程 https://mp.weixin.qq.com/s/f3LmUEtjIuLjkyjxJj7ebA 一文彻底了解DNS协议工作原理&…...
【宇宙回响】从Canvas到MySQL:飞机大战的全栈交响曲【附演示视频与源码】
🌟 这是星际大战系列的第三篇,感谢一路以来支持和关注这个项目的每一位朋友! 💡 文章力求严谨,但难免有疏漏之处,欢迎各位朋友指出,让我们一起在交流中进步。 🎁 项目代码、文档和相关资源都可以免费获取,希望能帮助到更多对游戏开发感兴趣的朋友。 💌 如果您有任…...
Linux内核内存管理 ARM32页表映射流程和案例分享
ARM32架构使用两级页表结构将虚拟地址转换为物理地址,以下为详细流程及案例分析: ARM32页表映射流程 1.获取页目录基地址 MMU通过TTBR(Translation Table Base Register)寄存器获取当前进程的一级页表(L1页表&#x…...
git push origin masterremote: [session-bd46a49f] The token username invalid
参考:如何把项目上传到Gitee(保姆级教程)_gitee上传项目-CSDN博客 1 新建仓库 username可以是登录账号的邮箱地址也可以是用户名 password可以是登录账号的密码也可以是私人令牌 2 创建分支 3 初始化 dev是你新建的分支 创建并切换分支 git init g…...
基于MCU实现的电机转速精确控制方案:软件设计与实现
本文将详细介绍一篇基于微控制器(MCU)的电机转速精确控制的软件方案。通过采样PWM信号控制和ADC采样技术,结合PID闭环控制算法,实现了电机转速的高效、稳定调节。以下是软件方案流程图,下文将对其进行展开讲解。 原图太…...
