实体类驱动建表:MyBatis-Plus自动生成DDL与代码生成实践
1. 项目思路拆解实体类当“唯一事实来源”1.1 传统流程里重复劳动有多痛写了十年SQL我原本以为自己最值钱的手艺就是建表和写CRUD。之前的项目节奏基本都是这样需求评审完先在建模工具里画出物理模型确认字段类型、长度、默认值、注释然后导出建表SQL到数据库里执行。表建完再打开IDE新建实体类把刚才表里那一堆字段重新翻译成Java类型写注释、写注解。如果有DBA团队中间还要把SQL脚本提交给DBA审核DBA改一版再返回来实体类也跟着改一版。这套流程最大的问题不是慢是同一份信息被反复手抄。表结构在建模工具里画一遍建表脚本里写一遍Java实体类里再写一遍后面的VO、DTO可能再来两遍。手抄必然出错而且出错方式非常隐蔽。我之前就踩过这种坑某张表的字段在数据库里定义成了VARCHAR(255)实体类里却抄成了VARCHAR(2550)当时看着不明显后来数据涨起来某条数据刚好多出一个字符线上插入直接报Data too long查了大半天才发现是实体定义和真实表结构对不上。算一笔时间账。一个中等业务模块大概10到20张表每张表平均15个字段。一位熟练开发从画模型到写建表SQL再到手写实体类基本三个小时起步。中间要是需求改两轮表结构跟着改这个时间还得翻倍。十年下来这种机械重复劳动消耗掉的时间非常可观而且没有一点技术含量。所以这个项目换新架构时我给自己定了一条原则建表SQL和实体类能交给工具生成的绝对不动手敲。1.2 两条自动化路线实体出DDL表结构出实体这个项目里我采用的思路核心是让Java实体类成为表结构的“唯一事实来源”。数据库表和Java领域模型本质上描述的是同一组业务数据只不过一个用SQL的语法表达一个用Java的语法表达。信息既然是同一份就没有理由在两个地方各写一遍。只要实体类定义是权威的、完整的表结构就可以完全由它推导出来。围绕这条原则整个流程拆成两个自动化的方向。第一个方向是正向生成新模块设计阶段先写Java实体类用MyBatis-Plus的注解把表名、列名、主键策略、字段映射这些元数据全部标注清楚然后通过一小段工具代码或者IDE插件直接从实体类反射出CREATE TABLE语句。新表上线连DDL都不用亲手写适合从零开始的新业务。第二个方向是反向生成如果项目里已经有一批遗留表或者DBA团队已经把物理模型定好了那就可以用MyBatis-Plus的AutoGenerator代码生成器根据数据库里的表结构直接生成实体类、Mapper、Service、Controller。这个方向适合老系统改造、新项目接入存量表。两个方向配合起来“从建表到实体”这件事就真正做到了零手写。这里没有任何黑科技MyBatis-Plus本身提供了完整的代码生成能力注解体系也很完善我要做的只是把这些现成能力串成一条自动化的链路再补一个自己用的DDL生成小工具。2. 正向生成让实体类自己产出建表SQL2.1 实体类上的注解要标到什么程度先看一个标准的实体类应该长什么样。MyBatis-Plus里最常用的三个注解是TableName、TableId和TableField。TableName标在类上指定表名TableId标在主键字段上说明主键策略TableField标在普通字段上可以指定列名、控制字段是否存在、配合自动填充等等。TableName(t_order) public class Order { TableId(value id, type IdType.AUTO) private Long id; TableField(order_no) private String orderNo; private String customerName; TableField(total_amount) private BigDecimal totalAmount; TableField(exist false) private String unStoredField; TableLogic private Integer deleted; }注解标注的程度直接决定DDL生成的质量有四个细节在实际项目中必须注意。第一TableField(exist false)的字段在生成DDL时必须跳过这类字段一般是关联查询的临时字段或者冗余展示字段数据库里根本没有对应列。第二主键类型一定要写清楚IdType.AUTO对应MySQL的自增列IdType.ASSIGN_ID是雪花算法主键数据库列定义成BIGINT就可以不需要自增。第三逻辑删除字段用TableLogic标注字段类型建议用Integer生成DDL时给个默认值0避免插入时出现NULL。第四乐观锁字段用Version标注类型建议Integer也建议加默认值0。MyBatis-Plus的注解体系本身就是完整的表元数据描述反射能拿到Java类型和字段名再结合注解信息就能完整还原一张表的物理结构。2.2 Java类型到MySQL类型的映射规则实体字段是Java类型建表SQL需要的是数据库类型中间必须要有一张清晰的映射表。默认映射规则要尽量贴近常见业务同时留出覆盖的余地。下面这张表是我在项目里实际使用的映射基于MySQL 8.0Java类型MySQL类型说明StringVARCHAR(255)长文本字段手动覆盖为TEXT或LONGTEXTLongBIGINT主键、雪花ID、时间戳均可用IntegerINT状态、数量等整型字段BooleanTINYINT(1)MySQL中布尔就是TINYINT(1)BigDecimalDECIMAL(18,2)金额字段忽略浮点误差LocalDateTimeDATETIME比TIMESTAMP更推荐后面说原因LocalDateDATE纯日期LocalTimeTIME纯时间DoubleDOUBLE浮点场景注意精度问题FloatFLOAT浮点场景byte[]BLOB二进制内容这里有几个选择是有考量的。日期时间类型我统一用DATETIME不用TIMESTAMP。原因一是MySQL的TIMESTAMP有2038年问题二是在时区配置不一致的环境里容易产生错乱。DATETIME不涉及时区转换读写更可控。Decimal金额字段不能用Double或Float二进制浮点数存在精度误差账算平这种事在业务里是事故级别的问题。String默认VARCHAR(255)覆盖80%以上的字段剩余的长文本、枚举文本靠columnDefinition单独覆盖。覆盖机制是这样设计的TableField里有一个columnDefinition属性可以写完整的列定义。我在工具里约定一旦这个属性有值就直接用它替代自动映射出来的数据类型不再做默认转换。这样既保证了默认规则的简洁也给特殊字段留了灵活的出口。2.3 一个可用的DDL生成器核心代码这个DDL生成器本质上是反射加字符串拼接核心代码非常短。下面这段代码基于Spring Boot和MyBatis-Plus环境可以直接放到项目工具包里面package com.example.ddl; import com.baomidou.mybatisplus.annotation.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; public class DdlGenerator { public static String generateCreateTableSql(Class? entityClass) { TableName tableName entityClass.getAnnotation(TableName.class); String table tableNameValue(entityClass, tableName); ListString columnDefs new ArrayList(); String primaryKeyDef null; String charset DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci; for (Field field : entityClass.getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) { continue; } TableField tableField field.getAnnotation(TableField.class); if (tableField ! null !tableField.exist()) { continue; } String columnName camelToUnderscore(field.getName()); if (tableField ! null !tableField.value().isEmpty()) { columnName tableField.value(); } TableId tableId field.getAnnotation(TableId.class); if (tableId ! null) { String colType mapJavaTypeToMysql(field.getType()); StringBuilder idDef new StringBuilder( columnName colType); if (tableId.type() IdType.AUTO) { idDef.append( AUTO_INCREMENT); } primaryKeyDef idDef.toString(); } else { String colType mapJavaTypeToMysql(field.getType()); columnDefs.add(String.format(%s %s NOT NULL COMMENT %s, columnName, colType, field.getName())); } } if (primaryKeyDef ! null) { columnDefs.add(0, primaryKeyDef COMMENT 主键); } StringBuilder sql new StringBuilder(); sql.append(CREATE TABLE IF NOT EXISTS ).append(table).append( (\n); sql.append(String.join(,\n, columnDefs)); if (primaryKeyDef ! null) { sql.append(,\n PRIMARY KEY (id)); } sql.append(\n) ENGINEInnoDB ).append(charset).append(;\n); return sql.toString(); } private static String tableNameValue(Class? entityClass, TableName tableName) { if (tableName ! null !tableName.value().isEmpty()) { return tableName.value(); } return camelToUnderscore(entityClass.getSimpleName()); } private static String mapJavaTypeToMysql(Class? javaType) { if (javaType String.class) return VARCHAR(255); if (javaType Long.class) return BIGINT; if (javaType Integer.class) return INT; if (javaType Boolean.class) return TINYINT(1); if (javaType BigDecimal.class) return DECIMAL(18,2); if (javaType LocalDateTime.class) return DATETIME; if (javaType LocalDate.class) return DATE; if (javaType LocalTime.class) return TIME; if (javaType Double.class) return DOUBLE; if (javaType Float.class) return FLOAT; if (javaType byte[].class) return BLOB; return VARCHAR(255); } private static String camelToUnderscore(String name) { return name.replaceAll(([a-z])([A-Z]), $1_$2).toLowerCase(); } public static void main(String[] args) { System.out.println(generateCreateTableSql(Order.class)); } }这段代码把主链路跑通了类名转表名、字段名转列名、Java类型转MySQL类型、主键识别、existfalse跳过。实际使用时可以把它封装成一个Spring Bean放在独立模块里或者做成本地命令行工具在启动时输出SQL文件。执行DDL时有两种路线。一种是工具生成.sql文件交给人审阅后再执行另一种是在工具里注入一个DataSource启动阶段直接执行。我更推荐第一种。建表SQL属于生产环境的重大变更全自动执行风险太高。工具生成初稿人工确认二次修改这个节奏最稳。2.4 主键、注释、默认值的处理细节主键策略值得单独说。MyBatis-Plus的IdType有AUTO、INPUT、ASSIGN_ID、ASSIGN_UUID几种。AUTO依赖数据库自增生成的DDL里列必须有AUTO_INCREMENTASSIGN_ID是雪花ID由应用侧生成数据库只要BIGINT字段即可。如果实体类没有加TableId注解工具默认把字段映射为BIGINT并在表末尾自动补上PRIMARY KEY。主键字段名建议统一用id这样工具生成的DDL里PRIMARY KEY (id)才不会标错列。注释这块工具默认把Java字段名当COMMENT生产环境肯定不行。我在实际项目里做了一层扩展读Swagger的Schema注解或者自定义的Comment注解优先取描述信息作为列注释两个都没有再回退到字段名。表结构注释是长期可维护性的关键裸表过几年根本没人记得字段含义维护成本极高。默认值处理是容易被忽略的细节。状态字段约定默认0或1逻辑删除字段默认0创建时间字段默认CURRENT_TIMESTAMP。这些都可以通过columnDefinition直接写完整定义TableField(columnDefinition DATETIME DEFAULT CURRENT_TIMESTAMP) private LocalDateTime createTime; TableField(columnDefinition INT DEFAULT 0) private Integer status;这样生成的SQL就完整了。插入数据时不填这些字段数据库会自动落默认值应用侧代码也能少几行赋值逻辑。3. 反向生成遗留表结构到实体类的一键方案3.1 FastAutoGenerator最小配置正向生成解决新表但真实项目里总有大量存量表。这些表结构是历史遗留的建表SQL可能写了七八年字段命名风格各异靠手写实体类去匹配纯属折磨。这时候最省力的做法是反向生成MyBatis-Plus官方提供的AutoGenerator新版叫FastAutoGenerator配置非常简单import com.baomidou.mybatisplus.generator.FastAutoGenerator; public class Generator { public static void main(String[] args) { FastAutoGenerator.create( jdbc:mysql://localhost:3306/biz?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai, root, password) .globalConfig(builder - builder .author(yourname) .outputDir(/tmp/mp-generator)) .packageConfig(builder - builder .parent(com.example.biz)) .strategyConfig(builder - builder .addInclude(t_user, t_order)) .execute(); } }执行完之后指定目录下会生成实体类、Mapper接口、XML文件、Service接口和ServiceImpl实现。实体类自动带TableName、TableId、TableField注解字段注释直接从数据库列的COMMENT读取字段类型映射由官方维护基本不会出错。这套能力大幅压缩了老表接入的工期。3.2 配置项里最容易踩的细节FastAutoGenerator的坑往往出在细节配置上。我实际总结下来下面这些配置项每个项目都要显式设置.strategyConfig(builder - builder .addInclude(t_user, t_order) .entityBuilder() .enableLombok() .logicDeleteColumnName(deleted) .versionColumnName(version) .enableTableFieldAnnotation() .naming(NamingStrategy.underline_to_camel))enableLombok生成Getter/Setter省掉一堆样板方法。enableTableFieldAnnotation强制每个字段都生成TableField注解这一步非常关键因为后面再用正向生成工具推DDL时依赖的就是这些注解。逻辑删除字段和乐观锁字段直接在配置里声明生成的实体类就会自动带上TableLogic和Version注解。命名策略要特别小心。数据库表名大多是下划线风格Java规范是驼峰underline_to_camel是默认且推荐的行为。但如果你遇到的表名是大小写混用的非标准风格NamingStrategy要改成no_change否则生成出来的实体类名可能跟真实表名对不上运行时直接报找不到表。还有一个版本兼容问题。MySQL 5.7和8.0的驱动、连接串有差异。连接8.0的库时连接串建议加上serverTimezoneAsia/Shanghai否则生成时间字段时可能报错或得到错误的时区。驱动版本最好和数据库大版本对齐别拿5.7的驱动连8.0的库就算能连上元数据读取也可能出现莫名其妙的问题。4. 实操中的坑与排查实录4.1 类型映射不合理的三类场景正向生成自动映射出来的类型至少有三类场景需要人工介入。第一类是类型映射结果不符合业务语义。String默认是VARCHAR(255)但邮箱、手机号、URL这些字段实际长度可能只要64或128用255既不精确又浪费索引空间描述、备注类字段内容可能很长VARCHAR(255)装不下需要手动改成TEXT。针对这些情况我建议在实体字段上用columnDefinition显式覆盖不要全量接受默认值。第二类是类型映射导致索引失效或报错。MySQL InnoDB下单列索引最大长度是3072字节8.0版本utf8mb4字符集下每个字符最多4字节所以VARCHAR(768)以上建立索引就可能超限。自动生成工具默认给String映射VARCHAR(255)如果某个字段被加上了索引单个字段问题不大但要是你手动把长度改成了1000还想建索引就会触发索引长度限制报错。大文本字段最稳妥的做法是用TEXT要么不建索引要么使用前缀索引要么冗余一个短字段用于查询。第三类是日期时间字段缺少默认值。LocalDateTime映射成DATETIME没有问题但创建时间、更新时间这些字段自动生成只会得到普通DATETIME列不会自动加DEFAULT CURRENT_TIMESTAMP。需要手动用columnDefinition覆盖创建时间加DEFAULT CURRENT_TIMESTAMP更新时间加DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP否则应用侧插入时还得手动赋值漏了就是NULL。4.2 执行DDL时的三类经典报错自动生成的DDL在真实环境执行时我遇到过的报错基本分三类。第一类是关键字冲突。表名或列名撞上MySQL保留字比如order、group、desc、status、rank这些。工具生成SQL时统一用反引号包裹表名和列名能规避掉大部分问题。但表名本身叫order的话即使建表时用了反引号后续MyBatis-Plus自动生成的查询SQL也可能出现冲突。最稳的解法是建表时就把表名改掉带上业务前缀比如t_order、biz_user。第二类是字符集不一致。工具生成的SQL里显式指定了utf8mb4和utf8mb4_general_ci但如果数据库实例默认字符集是latin1历史表迁移过来就很容易乱码。注意utf8mb4和utf8是两个不同的字符集MySQL里的utf8实际只是utf8mb3存不了emoji和部分生僻汉字新表一律用utf8mb4。建库的时候也建议统一把库级字符集设成utf8mb4。第三类是主键自增配置错位。实体类主键标注IdType.AUTO但表结构没有AUTO_INCREMENT插入数据时就会报错ERROR: Field id doesnt have a default value反过来表结构有自增但实体类标注ASSIGN_IDMyBatis-Plus会试图在应用侧生成主键导致双份主键逻辑冲突。排查方法很简单两边各看一遍实体里看TableId注解数据库里执行SHOW CREATE TABLE看列定义。4.3 表结构演进增量同步怎么做自动生成解决的是“建表”这个一次性动作但表结构的演进是持续发生的。实体类加了两个字段数据库里没有对应列总不能每次都把表DROP掉重建生产环境没人敢这么干。这个场景我目前的方案是引入Flyway或Liquibase做版本化迁移迁移脚本由人编写不完全追求自动化。实体类变更之后用DDL生成工具产出一份完整的CREATE TABLE脚本放到两个环境对比人工把差异整理成ALTER TABLE语句。对比工具可以用Navicat的表结构同步或者在测试库跑生成再和线上库的SHOW CREATE TABLE做diff。为了让这个增量过程更顺畅我坚持在实体类上改字段定义而不是直接改数据库然后定期用对比工具同步到测试环境。数据库变更记录以实体类上的注解为源头就不会出现改了一边忘了一边的情况。配合Flyway的版本化管理每次变更都有记录回滚也方便。4.4 团队里必须定的几条规范这套自动化流程要稳定运转团队必须定规则。规矩不是教条是为了让工具的输出保持可预期。第一条注释必须写。实体类属性至少有一句中文注释工具生成的列COMMENT直接取自注释没有注释的列在评审时直接打回。数据库表的可读性首先是靠COMMENT撑着。第二条主键策略必须显式声明。每个实体类都要有明确的TableId注解哪怕是默认的ASSIGN_ID也要写出来。依赖默认策略会导致生成的DDL和实际策略不一致。第三条禁止在实体类里塞业务方法。实体越纯净反射出来的DDL就越干净。字段上大量堆砌展示注解和业务注解反射时要排除的干扰项就越多工具代码会越来越复杂。第四条生成SQL必须人工Review。工具只能保证生成结果符合Java定义不能保证符合业务设计。字段长度是否合理、索引是否够用、默认值是否正确这些判断必须由人来完成。5. 收益、边界和一点延伸5.1 省掉的时间和更重要的正确率这个项目实际跑下来新增20张表左右的子系统从实体类写完到建表SQL评审通过大概省了三分之二的工时。以前要画模型、手写DDL、再手抄实体现在只需要在实体类上把注解和注释写清楚一条命令生成SQL评审后直接执行。比节省时间更重要的是正确率。字段名、字段类型、字段注释这三样东西以前在两个文件里各出现一次总有一方会滞后。现在源头只有一个实体类表结构由它生成只要生成规则稳定表和实体定义不一致的问题就从根本上消失了。这个收益在长期维护中特别明显需求变更时改一个文件另一个产物自动跟着变。5.2 这套方案不适合什么说实话这个方案不是银弹。它解决的是“实体类定义到建表DDL”这段重复劳动但表结构设计本身还是要人来做。哪些字段应该有、主键用什么策略、要不要冗余、索引怎么设计这些决策生成器替代不了。工具生成的是“符合Java类型的SQL”不是“符合业务设计的SQL”。复杂表结构的支持也比较有限。联合主键、复合索引、分区表、生成列、外键约束这些在实体类上表达非常别扭。碰到这类表我建议回归传统方式手动写建表SQL实体类再用反向生成去匹配。工具是服务人的不是为了自动化而绑架人。5.3 后续可以怎么扩展这个思路继续延伸有几个方向值得做。一个是把生成的工具做成Maven插件编译时自动产出DDL文件到target目录和CI流程集成生成一次、审阅一次、归档一次。另一个是和Flyway集成从实体类直接生成V版本迁移脚本把开发和数据库变更串成一条链。还有一个方向是反向扩展表结构定义好之后不只生成Java实体还能生成TypeScript类型定义和前端表单字段的元数据前后端共用一套“唯一事实来源”。我在实际使用中有一个习惯一直保留每次生成SQL之后把SQL脚本存到项目源码的db目录下标注生成时间和对应实体类的commit号。以后有人问“这张表的字段什么时候加的、为什么加”翻一下commit记录和SQL脚本就能对上号比只依赖数据库元数据可靠得多。最后再分享一个小技巧如果用Lombok反射拿字段时用getDeclaredFields()直接拿到有效字段列表。不要用getMethods()去推字段那会把父类的方法、IDE生成的合成方法都算进来生成的DDL会莫名其妙多出几列。getDeclaredFields()配合注解反射是目前最稳的组合。

相关新闻

OpenHarmony上RN错误边界与白屏问题全链路排查方案

OpenHarmony上RN错误边界与白屏问题全链路排查方案

1. 为什么在OpenHarmony上做RN要重新审视错误边界先从这次项目的起点说起。团队在适配React Native到OpenHarmony平台时,最头疼的不是JS层面的兼容问题,反而是看起来不起眼的崩溃和白屏。很多开发者第一次跑通RN on OpenHarmony时,都会遇到一…

2026/10/9 4:22:46 阅读更多 →
ESP-Mosaico:模块化硬件方案让ESP32原型开发像拼马赛克

ESP-Mosaico:模块化硬件方案让ESP32原型开发像拼马赛克

ESP-Mosaico这个名字第一次出现在我眼前的时候,我以为是乐鑫做的某种图形界面库——毕竟mosaico在西班牙语里就是“马赛克”,听起来像是把图像拼成一块一块的东西。真正点开项目文档才发现,它其实是一套模块化硬件开发方案,把主控…

2026/10/9 4:22:46 阅读更多 →
时间自由缩放:超越压缩的智能架构如何控制时间维度

时间自由缩放:超越压缩的智能架构如何控制时间维度

我们其实已经站在了一个很有意思的拐点上。过去十年,智能系统最大的进展,表面上是模型越做越大、能力越做越强,但本质上就干了一件事:压缩。把语言压缩成token,把图像压缩成embedding,把世界知识压缩进权重…

2026/10/9 4:22:46 阅读更多 →

最新新闻

LRE框架:重构AI智能体的时间感知与因果记忆机制

LRE框架:重构AI智能体的时间感知与因果记忆机制

1. 这不是“给AI加个备忘录”,而是重构智能体的时间感知能力很多人第一次看到“AI智能体记忆管理”这个词,下意识会想:不就是让大模型多存点上下文、加个向量数据库当外挂硬盘吗?我试过——在某个模拟项目X里,给一个任…

2026/10/9 4:48:03 阅读更多 →
10分钟上手 douyin-downloader:抖音批量下载与无水印提取完整指南

10分钟上手 douyin-downloader:抖音批量下载与无水印提取完整指南

10分钟上手 douyin-downloader:抖音批量下载与无水印提取完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fal…

2026/10/9 4:48:03 阅读更多 →
answer-me-with-html 完整参考指南:从 Markdown 稿件格式到代码块、自定义主题与 STE 写作检查

answer-me-with-html 完整参考指南:从 Markdown 稿件格式到代码块、自定义主题与 STE 写作检查

【免费下载链接】answer-me-with-html Answer me with HTML — an agent skill that answers hard questions with a one-page HTML you can actually read. 让 AI Agent 用一页 HTML 回答复杂问题。 项目地址: https://gitcode.com/gh_mirrors/an/answer-me-with-h…

2026/10/9 4:48:03 阅读更多 →
ponytail插件使用指南:skill模块配置与效率提升实践

ponytail插件使用指南:skill模块配置与效率提升实践

1. 从“ponytail”这个标题说起:它到底是什么第一次看到“ponytail”这个词,大多数人脑子里蹦出来的画面是扎在脑后的那束马尾辫。但如果它出现在技术社区、插件市场或者效率工具的讨论里,那它大概率不是发型教程,而是一个被开发者…

2026/10/9 4:48:03 阅读更多 →
Java电商系统实战:JSP+JavaBean+SQL Server全链路可运行方案

Java电商系统实战:JSP+JavaBean+SQL Server全链路可运行方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 4:48:03 阅读更多 →
HermesWorkspace Playground 可选 3D NPC 模型替换指南:基于 GLB 的 Voxel 身体升级方案

HermesWorkspace Playground 可选 3D NPC 模型替换指南:基于 GLB 的 Voxel 身体升级方案

【免费下载链接】hermes-workspace Native web workspace for Hermes Agent — chat, terminal, memory, skills, inspector. 项目地址: https://gitcode.com/gh_mirrors/he/hermes-workspace 点击查看 免费下载 本文依据仓库 public/avatars-3d/README.md 编写&am…

2026/10/9 4:47:02 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →