MyBatis-Plus更新操作深度解析:从ID更新到条件更新的实战指南
1. 项目概述为什么MyBatis-Plus的更新操作值得深挖如果你用过MyBatis肯定对写Update SQL语句手动拼接set字段处理null值以及确保where条件精准这些琐事记忆犹新。一个不小心id1写成id2或者漏了某个字段的判空线上bug就来了。MyBatis-Plus简称MP的出现很大程度上就是为了把这些重复、易错的体力活自动化。而它的更新操作尤其是通过id更新和条件更新正是日常CRUD中最高频、也最考验框架设计功力的部分。我见过不少团队引入MP后更新代码写得五花八门。有人图省事不管三七二十一直接new Entity()然后调用updateById结果把数据库里不该改的字段也刷成了null。也有人过度设计明明一个简单的按ID更新非要自己构造一个复杂的UpdateWrapper。这些用法不仅影响代码的可读性和维护性更可能埋下数据不一致的隐患。今天我们就来彻底拆解MP的更新操作不光是看API怎么用更要弄明白背后的设计逻辑、性能考量和那些官方文档里没写的“坑”。无论你是刚接触MP的新手还是想优化现有代码的老手相信这篇从实战中总结出来的经验都能让你对update有一个全新的认识。2. 核心设计思想MP更新操作的两种范式与底层逻辑MP的更新操作主要围绕两个核心方法展开updateById(T entity)和update(T entity, WrapperT updateWrapper)。这看似简单的二分法背后却对应着两种截然不同的数据操作范式和ORM设计哲学。2.1 通过ID更新实体驱动与“选择性更新”updateById是MP中最符合“面向对象”思维的更新方式。它的逻辑非常直接你提供一个实体对象EntityMP会根据这个实体对象的主键通常是id字段去定位数据库中的记录然后用实体对象中非空的字段值去更新对应的数据库列。这里的关键词是“非空”。MP默认启用了“非空字段更新”策略。这意味着当你执行userMapper.updateById(user)时MP生成的SQL语句只会包含user对象中那些值不为null的字段。比如你只想更新用户的邮箱那么你可以这样操作User user new User(); user.setId(1L); user.setEmail(new_emailexample.com); userMapper.updateById(user);生成的SQL会是UPDATE user SET email ? WHERE id ?。name,age等其他字段即使为null也不会出现在SET子句中从而避免了意外地用null覆盖掉原有的有效数据。这个特性在部分更新场景下非常安全和便捷。注意这个“非空”判断是基于Java对象的字段值。如果你的业务逻辑中确实需要将某个字段更新为null例如清空用户的昵称那么这种默认策略就会成为障碍。这时你有几种选择1使用后续会讲到的UpdateWrapper2在字段上使用MP的TableField注解并设置strategy FieldStrategy.IGNORED但这样会全局忽略该字段的空值判断需谨慎3使用update方法并同时提供实体和Wrapper。这种方式的优势在于意图清晰代码简洁与领域模型结合紧密。但它也有局限它严重依赖于实体对象的状态并且一次只能更新一条记录通过主键。2.2 条件更新Wrapper驱动与批量操作思维update(T entity, WrapperT updateWrapper)则提供了更强大、更灵活的更新能力。它结合了一个可选的实体对象和一个条件包装器UpdateWrapper。这里的实体对象用于提供需要更新的字段和值而UpdateWrapper则用于构造复杂的WHERE条件甚至可以替代实体对象直接设置更新字段。这种范式是“查询驱动”或“条件驱动”的。它允许你批量更新通过Wrapper构造条件匹配多条记录实现批量更新。更新特定字段为特定值即使这个值是null也可以通过Wrapper明确指定。执行更复杂的更新逻辑例如set一个字段为原值加减setSql(age age 1)或者根据另一个字段的值进行更新。它的基本形态如下// 方式1Entity Wrapper (Entity用于Set值Wrapper用于Where条件) User updateEntity new User(); updateEntity.setStatus(1); UpdateWrapperUser wrapper new UpdateWrapper(); wrapper.eq(dept_id, 10).lt(age, 30); userMapper.update(updateEntity, wrapper); // 生成SQL: UPDATE user SET status 1 WHERE dept_id 10 AND age 30 // 方式2仅使用Wrapper (同时用Wrapper设置Set值和Where条件) UpdateWrapperUser wrapper new UpdateWrapper(); wrapper.set(status, 1).set(update_time, LocalDateTime.now()) // 设置更新值 .eq(dept_id, 10); // 设置条件 userMapper.update(null, wrapper); // 生成SQL: UPDATE user SET status 1, update_time ? WHERE dept_id 10理解这两种范式的区别是写好MP更新代码的基础。简单来说“按ID更新”适合对单条记录的已知实体进行部分字段修补而“条件更新”则适合基于业务规则对一组记录进行定向变更。3. 通过ID更新的深度解析与最佳实践虽然updateById看起来简单但想用得“稳”里面有不少细节需要注意。3.1 主键识别与“雪花算法”ID的坑MP默认使用id作为主键列名。如果你的表主键字段不叫id需要在实体类字段上使用TableId注解来指定。这里最常遇到的一个坑是主键生成策略。MP内置了多种主键生成策略比如ASSIGN_ID默认使用雪花算法和AUTO数据库自增。当你使用ASSIGN_ID时MP会在插入前自动为id字段生成一个长整型数值。问题在于这个数值可能非常大例如1191567216984836098L。在更新操作时如果你从前端接收了一个JSON反序列化出来的实体对象其id字段是String类型前端JS数字精度问题常传字符串或者因为序列化/反序列化导致长整型精度丢失就会造成id不匹配更新失败。实操心得在前后端交互中对于雪花算法生成的Long型ID建议后端统一以String类型提供给前端前端也以String类型传回以避免精度丢失。在接收更新请求时不要直接反序列化到Entity就调用updateById。应先根据ID从数据库查询出最新实体再将需要更新的字段拷贝过去然后再更新。这虽然多了一次查询但保证了数据的安全性和一致性也是“乐观锁”等机制实现的基础。3.2 字段更新策略控制TableField注解的妙用如前所述MP默认忽略null字段。但业务场景是复杂的。例如有一个description字段用户可能想将其更新为“一段新描述”也可能想清空它设置为null。为了应对这种场景MP提供了字段策略配置。你可以在实体类的字段上使用TableField注解TableField(strategy FieldStrategy.IGNORED)忽略空值检查该字段无论是否为null都会参与SQL生成。慎用因为它会覆盖全局配置容易导致误更新。TableField(strategy FieldStrategy.NOT_NULL)非null才更新且字段为null时会报错在插入时常用。TableField(strategy FieldStrategy.NOT_EMPTY)对于字符串非空not empty才更新比NOT_NULL更严格。更常见的做法是不修改实体注解而是在需要更新null值时转而使用UpdateWrapperUpdateWrapperUser wrapper new UpdateWrapper(); wrapper.eq(id, 1L).set(description, null); // 明确将description设置为null userMapper.update(null, wrapper);3.3 乐观锁的集成与并发更新处理在高并发场景下直接updateById可能导致“更新丢失”。MP提供了基于版本号的乐观锁支持。首先在实体类中增加一个用Version标记的字段通常是Integer或Long类型的version。Version private Integer version;然后在配置中开启乐观锁插件Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }启用后每次执行updateById或带版本的update时MP会自动在WHERE条件中加上version #{oldVersion}并在SET部分执行version version 1。如果更新时发现数据库中的version与实体携带的version不一致说明已被其他线程修改更新行数就会为0。业务代码可以根据这个返回值进行重试或提示冲突。注意事项乐观锁插件只对updateById和update(entity, wrapper)方法生效并且要求wrapper不能复用即不能使用EntityWrapper必须用UpdateWrapper或LambdaUpdateWrapper。开启后所有相关更新操作都必须携带正确的版本号。通常的做法是先selectById获取当前实体带最新版本号修改业务字段然后调用updateById。4. 条件更新的高级用法与性能陷阱条件更新的强大来自于UpdateWrapper及其Lambda版本LambdaUpdateWrapper的灵活构建。但能力越大责任越大用不好就容易掉坑里。4.1 UpdateWrapper vs LambdaUpdateWrapper可读性与安全性的权衡UpdateWrapper允许你使用字符串形式的列名UpdateWrapperUser wrapper new UpdateWrapper(); wrapper.eq(user_type, 1).set(status, 2);这种方式写起来快但有个致命缺点魔法值。字符串user_type和status在编译期无法检查如果数据库表字段名变更或者你手抖打错了字只有在运行时执行SQL报错时才能发现。因此强烈推荐使用LambdaUpdateWrapperLambdaUpdateWrapperUser wrapper new LambdaUpdateWrapper(); wrapper.eq(User::getUserType, 1).set(User::getStatus, 2);它通过方法引用来指定字段是类型安全的。IDE可以提供代码补全和重构支持极大地减少了出错概率。虽然Lambda表达式在极少数极端性能敏感场景可能有微乎其微的开销但对于绝大多数业务系统其带来的可维护性提升是绝对值得的。4.2 复杂条件的构建AND、OR与嵌套Wrapper支持构建非常复杂的查询条件这在更新场景下同样有用。// 更新部门为10且年龄小于30或者部门为20且状态为0的用户 LambdaUpdateWrapperUser wrapper new LambdaUpdateWrapper(); wrapper .and(wp1 - wp1.eq(User::getDeptId, 10).lt(User::getAge, 30)) .or(wp2 - wp2.eq(User::getDeptId, 20).eq(User::getStatus, 0)) .set(User::getLevel, 3);生成的SQL类似于UPDATE user SET level 3 WHERE (dept_id 10 AND age 30) OR (dept_id 20 AND status 0)。踩坑记录注意and和or方法接收的是一个ConsumerWrapper函数式接口。在嵌套条件时逻辑一定要理清。一个常见的错误是混淆了and和or的优先级导致更新了意料之外的数据。建议在编写复杂条件时先用注释写下SQL逻辑再转化成Wrapper代码。4.3 直接执行SQL片段setSql的威力与风险UpdateWrapper提供了setSql方法允许你直接设置更新SQL片段。这用于实现一些MP默认不支持的更新逻辑比如基于原值的计算更新wrapper.setSql(balance balance - 50, points points 10);这非常强大可以一步完成“扣减余额并增加积分”的操作且是原子性的。警告setSql是一把双刃剑。它绕过了MP的字段映射和参数化查询如果参数来自用户输入必须严格防范SQL注入。绝对不要将用户输入的字符串直接拼接进setSql。正确的做法是使用参数化方式尽管在setSql中这有点别扭但更安全的方式是考虑将其拆分为多个set操作或使用MP的apply方法它也是参数化的。4.4 批量更新的性能考量与“伪批量”真相很多人会问MP如何做批量更新比如我有一个ID列表想批量更新这些记录的状态。MP的update方法本身支持通过Wrapper的in条件实现批量更新ListLong idList Arrays.asList(1L, 2L, 3L); LambdaUpdateWrapperUser wrapper new LambdaUpdateWrapper(); wrapper.in(User::getId, idList).set(User::getStatus, 9); userMapper.update(null, wrapper);这看起来是“批量”更新但本质上生成的是一条SQLUPDATE user SET status 9 WHERE id IN (1, 2, 3)。这对于数据库来说仍然是一次请求、一次事务取决于你的事务边界内的操作是真正高效的批量操作。需要警惕的是另一种“伪批量”在循环中多次调用updateById。for (User user : userList) { userMapper.updateById(user); }这会产生N条SQL语句发起N次网络请求如果使用数据库连接池性能开销巨大。务必避免这种写法。正确的做法就是上面提到的用IN条件构造一个UpdateWrapper一次性更新。如果更新值不同例如每条记录要设置不同的状态则需要考虑使用ExecutorType.BATCH模式但这已经超出了MP的简单封装范畴更接近原生MyBatis的批处理操作。5. 实战场景下的常见问题与排查技巧理论说再多不如踩几个坑来得实在。下面是我在实际项目中遇到的几个典型问题及其解决方案。5.1 更新成功但影响行数为0可能的原因排查调用updateById或update方法返回的int是受影响的行数。如果返回0表示没有记录被更新。别急着下“更新失败”的结论要系统排查ID不存在这是最直接的原因。检查传入的实体ID是否正确或者对应的记录是否已被删除。乐观锁冲突如果启用了乐观锁检查传入实体的version字段值是否与数据库中的当前版本一致。不一致则更新会返回0。条件不匹配对于条件更新仔细检查UpdateWrapper构建的条件是否过于严格导致没有记录满足条件。建议先将Wrapper转换成查询条件selectCount一下看看能匹配多少条记录。数据未变化MP比较“智能”如果你要设置的新值与数据库中该字段的当前值完全一样MP可能会优化掉这个更新具体行为取决于配置和版本导致影响行数为0。这通常不是问题但如果你依赖影响行数做业务判断就需要留意。全局拦截器过滤你是否配置了MP的“租户插件”、“数据权限插件”等这些插件可能会在WHERE条件中自动添加一些过滤条件如tenant_id xxx导致你期望更新的记录不在可更新范围内。排查步骤开启MP的SQL日志输出配置mybatis-plus.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl。查看控制台打印出的最终执行的SQL语句和参数。将这条SQL直接拿到数据库客户端执行验证是否能更新到数据。这是最直接的调试方法。5.2 字段更新不符合预期空值、默认值与类型转换场景想将某个数字字段更新为0但更新后数据库里还是原来的值。原因MP的默认字段策略是忽略null但基本数据类型如int的默认值是0不是null。所以当你setStatus(0)时MP认为这个字段有值0会生成更新语句。但如果你的字段策略被错误地配置为NOT_NULL或NOT_EMPTY而0可能被某些策略视为“空值”就会出问题。更常见的是实体类中用了int而你想表达“不更新此字段”但int无法表示null。最佳实践是实体类中的字段尤其是可能不需要更新的字段尽量使用包装类型Integer,Long,String。类型转换错误通过Wrapper的set方法如果传入的值类型与数据库字段类型不匹配MP会尝试类型转换。但某些转换可能失败或产生意外结果。例如传入一个Date对象给varchar字段。建议保持类型一致。5.3 关于“全表更新”的严重警告这是一个极其危险的错误如果你在构造UpdateWrapper时忘记了添加.eq()或其他任何条件那么生成的SQL将没有WHERE子句变成UPDATE user SET ...。这将更新整张表的所有数据如何避免代码审查对任何使用update(null, wrapper)或update(entity, wrapper)的代码必须严格审查wrapper是否包含了有效的、明确的条件。使用LambdaWrapper在一定程度上LambdaWrapper的方法链式调用能提醒你构造条件。数据库权限在开发、测试、生产环境中给应用程序使用的数据库账号应该遵循最小权限原则。对于核心业务表可以考虑不授予应用程序UPDATEwithout WHERE的权限但这通常难以细化控制。事务与备份在执行任何批量更新或条件更新前务必在事务内操作。这样一旦发现更新行数远超预期可以立即回滚。对于生产环境的重要数据更新操作前进行备份是铁律。5.4 更新操作中的事务管理MP本身不管理事务事务需要由Spring的Transactional注解或编程式事务来管理。一个关键点是更新操作和获取更新条件的查询操作应该放在同一个事务里。典型的错误模式// 错误示例 public void updateUserStatus(Long id, Integer newStatus) { User user userMapper.selectById(id); // 事务A if (user ! null someCondition) { user.setStatus(newStatus); userMapper.updateById(user); // 事务B } }如果someCondition依赖于查询出来的user状态而在事务A和事务B之间其他线程修改了这条记录就可能出现数据竞态。正确的做法是让查询和更新在同一个事务中或者使用乐观锁机制。// 正确示例查询更新在同一事务内 Transactional(rollbackFor Exception.class) public void updateUserStatus(Long id, Integer newStatus) { User user userMapper.selectById(id); if (user ! null user.getOldStatus().equals(1)) { // 使用查询到的值做判断 user.setStatus(newStatus); userMapper.updateById(user); } } // 或者使用乐观锁更优 public void updateUserStatus(Long id, Integer newStatus) { User user userMapper.selectById(id); if (user ! null user.getOldStatus().equals(1)) { user.setStatus(newStatus); int rows userMapper.updateById(user); // 自带版本检查 if (rows 0) { throw new OptimisticLockingFailureException(数据已被修改请重试); } } }6. 性能优化与扩展思考当数据量增大时更新操作的性能也需要被关注。6.1 索引与更新条件Update操作的性能瓶颈主要在WHERE条件的查找上。确保UpdateWrapper中用于过滤条件的字段尤其是等值查询eq和范围查询lt,gt,in的字段上建立了合适的数据库索引。没有索引的全表扫描对于更新操作是灾难性的因为它会锁住大量记录。6.2 大批量数据更新的替代方案对于数万甚至百万级别的数据更新即使使用IN条件一条巨大的UPDATE ... WHERE id IN (...)语句也可能对数据库造成压力长事务、锁竞争、binlog过大。这时可以考虑分批次更新public void batchUpdateStatus(ListLong idList, Integer status) { int batchSize 1000; // 每批1000条 ListListLong partitions Lists.partition(idList, batchSize); for (ListLong partition : partitions) { LambdaUpdateWrapperUser wrapper new LambdaUpdateWrapper(); wrapper.in(User::getId, partition).set(User::getStatus, status); userMapper.update(null, wrapper); // 可以考虑每批提交后稍作停顿减轻数据库压力 // Thread.sleep(10); } }对于更复杂的、需要关联多表计算更新值的场景MP的Wrapper可能就力不从心了。这时回归原生MyBatis编写一条高效的、基于集合操作的更新SQL或者在数据库端使用存储过程往往是更优的选择。MP并不排斥这种做法你可以在Mapper中定义自己的update方法使用Update注解编写自定义SQL享受MP带来的依赖注入等便利同时获得极致的性能。6.3 监听器与自动填充让更新更“智能”MP提供了MetaObjectHandler接口可以实现插入和更新时的自动字段填充。这对于create_time,update_time,update_by更新人等通用字段非常有用。Component public class MyMetaObjectHandler implements MetaObjectHandler { Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); this.strictUpdateFill(metaObject, updateBy, String.class, getCurrentUsername()); // 从线程上下文获取当前用户 } }在实体类字段上添加TableField(fill FieldFill.UPDATE)注解当执行updateById或update(entity, wrapper)时这些字段会自动被填充无需在业务代码中手动设置。这保证了数据更新的规范性和一致性是大型项目必备的实践。最后我想说的是工具的价值在于让人更专注于业务逻辑。MyBatis-Plus的更新操作封装已经覆盖了90%以上的日常场景。理解清楚updateById和条件更新的本质区别熟练掌握LambdaUpdateWrapper的链式调用并时刻警惕全表更新、空值、事务等陷阱你就能写出既安全又高效的数据库更新代码。剩下的10%复杂场景知道何时该跳出框架使用更底层的工具这才是资深开发者应有的判断力。

相关新闻

.NET ArrayPool.Shared:高性能内存管理实战指南

.NET ArrayPool.Shared:高性能内存管理实战指南

1. ArrayPool.Shared 深度解析:高性能内存管理的秘密武器在.NET开发中,内存分配和垃圾回收(GC)一直是性能优化的重点领域。当我们需要频繁创建和销毁数组时,传统的new操作会导致大量内存分配和GC压力,这正是ArrayPool.Shared大显身…

2026/9/22 18:49:38 阅读更多 →
Vivado仿真器入门:从零掌握Verilog代码验证与调试

Vivado仿真器入门:从零掌握Verilog代码验证与调试

1. 项目概述:为什么仿真器是Verilog学习的“第一道门”如果你刚开始接触Verilog,可能已经写了一些简单的代码,比如一个与门或者一个计数器。但代码写完了,你怎么知道它到底能不能工作?是直接烧录到FPGA板子上看灯闪不闪…

2026/9/23 1:59:44 阅读更多 →
深度学习如何改变化学研究:DeepChem从分子设计到药物发现的完整指南

深度学习如何改变化学研究:DeepChem从分子设计到药物发现的完整指南

深度学习如何改变化学研究:DeepChem从分子设计到药物发现的完整指南 【免费下载链接】deepchem Democratizing Deep-Learning for Drug Discovery, Quantum Chemistry, Materials Science and Biology 项目地址: https://gitcode.com/GitHub_Trending/de/deepchem…

2026/9/22 3:53:53 阅读更多 →

最新新闻

React Styleguidist 文档页 Markdown 语法全解析:以 sections 示例 One.md 为例

React Styleguidist 文档页 Markdown 语法全解析:以 sections 示例 One.md 为例

React Styleguidist 文档页 Markdown 语法全解析:以 sections 示例 One.md 为例 【免费下载链接】react-styleguidist Isolated React component development environment with a living style guide 项目地址: https://gitcode.com/gh_mirrors/re/react-stylegui…

2026/9/23 18:42:54 阅读更多 →
2025大模型知识蒸馏实战:精度、速度与可解释性三重平衡

2025大模型知识蒸馏实战:精度、速度与可解释性三重平衡

简介:本资源是一份面向AI工程师与大模型实践者的《2025大模型知识蒸馏指南(详细)》深度技术手册,聚焦DeepSeek等主流大模型背景下的知识蒸馏落地路径,系统解决模型压缩、推理加速与边缘部署难题。内容覆盖蒸馏核心原理…

2026/9/23 18:42:54 阅读更多 →
OOMWOO 开源扫地机器人边刷电机、边刷与充电触点部件规格详解

OOMWOO 开源扫地机器人边刷电机、边刷与充电触点部件规格详解

OOMWOO 开源扫地机器人边刷电机、边刷与充电触点部件规格详解 【免费下载链接】oomwoo Open-source vacuum robot cleaner 项目地址: https://gitcode.com/gh_mirrors/oo/oomwoo 本文以 contributions/part-specs/OsakaTX/side-brush-charging-contacts-specs.md&#xf…

2026/9/23 18:42:54 阅读更多 →
3个技巧搞定U糖性能优化,告别代码报错

3个技巧搞定U糖性能优化,告别代码报错

3个技巧搞定U糖性能优化,告别代码报错 刚接手项目,复制了一段处理高精度计算的代码,结果跑起来直接报错,日志里全是 NaN…

2026/9/23 18:42:54 阅读更多 →
Eclipse Mosquitto 认证插件机制全解析:从社区实践到官方插件架构

Eclipse Mosquitto 认证插件机制全解析:从社区实践到官方插件架构

后端消息队列消息路由 【免费下载链接】mosquitto Eclipse Mosquitto - An open source MQTT broker 项目地址: https://gitcode.com/gh_mirrors/mos/mosquitto 点击查看 免费下载 本篇技术指南以 Mosquitto 官方博客于 2013 年发布的《Authentication plugins》一…

2026/9/23 18:42:53 阅读更多 →
告别配置地狱:11110实战最佳实践

告别配置地狱:11110实战最佳实践

告别配置地狱:11110实战最佳实践 配置环境就卡半天?这是无数开发者在接手新项目时的真实写照。依赖版本冲突、环境变量缺失、本地与生产环境差异巨大,这些琐碎问题往往比写业务逻辑更耗时。想要彻底解决这个痛点,不能只靠玄学,必须建立一套可复现、…

2026/9/23 18:41:52 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →