MyBatis传List调Oracle存储过程批量插入实战
简介这份资源面向使用 Mybatis 与 Oracle 的 Java 后端开发者聚焦于如何将 List 类型参数传入 Oracle 存储过程以实现批量插入数据解决 Mybatis 批处理难以实时返回主键、foreach 循环集合长度受限、事务回滚不便等痛点。资源以 PDF 形式呈现压缩包内共 1 个文件大小约 61KB内容围绕数据库表与 Oracle 对象类型、数组类型的建立、存储过程编写、Mybatis parameterMap 与 TypeHandler 配置以及服务端调用方式展开并给出 ListHandler 将 Java List 转换为 Oracle ARRAY 的关键实现思路。目前已有 1961 人学习适合需要掌握 Mybatis 调用存储过程传集合参数、灵活控制事务回滚的中高级开发者参考可帮助读者理解参数封装与批量插入的完整链路并据此排查实际项目中的传参报错问题。1. 批量写库卡在存储过程那一步MyBatis 传 List 调 Oracle 到底难在哪单条insert循环一万次数据库连接池被打满接口超时报警——这是很多做批量数据落库的开发者都遇到过的场景。把循环改成一次调用 Oracle 存储过程、把 List 当参数整体传进去是常见的优化方向。但真动手时你会发现MyBatis 的#{}对 List 并不友好Oracle 的存储过程也不认识 Java 的ArrayList中间隔着一层类型系统的鸿沟。这篇笔记讲的就是怎么把这道鸿沟填上从 Oracle 自定义类型定义、MyBatis 的TypeHandler编写到 Mapper XML 里statementTypeCALLABLE的写法再到批量提交时的参数上限和事务边界。适合正在做批量入库优化、或者被ORA-06550、invalid column type这类报错卡住的开发者。下面按我实际落地的顺序拆开讲。2. 先搞清楚 Oracle 侧的接收容器自定义 Type 和 Array 怎么建2.1 为什么不能直接把 Java List 塞进存储过程Oracle 存储过程的参数类型是数据库层面的类型Java 的ListT在 JDBC 层面没有直接对应物。你写#{list}传一个ArrayListMyBatis 默认会尝试用UnknownTypeHandler去猜结果通常是invalid column type或者参数个数不匹配。正确的思路是在 Oracle 里定义一个OBJECT TYPE描述单行结构再定义一个TABLE TYPE也就是嵌套表描述多行集合存储过程的入参用这个TABLE TYPE。Java 侧则通过 JDBC 的ARRAY或者 MyBatis 的TypeHandler把 List 映射成这个嵌套表。这个设计的好处是一次网络往返传一批数据存储过程内部用FORALL或普通循环批量写性能比逐条 JDBC 调用高一个量级。代价是类型定义要提前在数据库里建好不能像临时表那样随用随建。2.2 建 TYPE 的 SQL 和三个容易忽略的细节假设要批量插入的是用户订单数据单行结构包含订单号、用户 ID、金额三个字段。先建 OBJECT TYPE-- 单行结构字段类型要和目标表列类型对齐 CREATE OR REPLACE TYPE T_ORDER_ROW AS OBJECT ( order_no VARCHAR2(64), user_id NUMBER(18), amount NUMBER(12,2) ); / -- 嵌套表类型元素是上面的 OBJECT CREATE OR REPLACE TYPE T_ORDER_TAB AS TABLE OF T_ORDER_ROW; /这里有三个细节容易翻车。第一VARCHAR2的长度要和目标表列一致或更长短了会在存储过程内部赋值时抛ORA-06502。第二NUMBER的精度如果不写默认是NUMBER无精度和表列的NUMBER(12,2)在隐式转换时可能产生精度丢失建议显式对齐。第三CREATE OR REPLACE TYPE如果被其他 TYPE 或存储过程引用替换时会报ORA-02303需要先删依赖或加FORCE选项——生产环境改 TYPE 要格外小心我一般先在测试库验证。2.3 存储过程怎么写入参、循环和异常处理存储过程接收T_ORDER_TAB内部遍历插入CREATE OR REPLACE PROCEDURE P_BATCH_INSERT_ORDER ( p_orders IN T_ORDER_TAB, p_result OUT NUMBER ) AS BEGIN -- 入参为空直接返回避免空集合遍历报错 IF p_orders IS NULL OR p_orders.COUNT 0 THEN p_result : 0; RETURN; END IF; FORALL i IN 1 .. p_orders.COUNT INSERT INTO T_ORDER ( order_no, user_id, amount, create_time ) VALUES ( p_orders(i).order_no, p_orders(i).user_id, p_orders(i).amount, SYSDATE ); p_result : SQL%ROWCOUNT; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; p_result : -1; RAISE; END; /FORALL比普通FOR循环快因为它把多次 INSERT 批量发给 SQL 引擎减少了 PL/SQL 和 SQL 引擎之间的上下文切换。SQL%ROWCOUNT拿到实际插入行数通过OUT参数回传给 Java 侧做校验。异常处理里先ROLLBACK再RAISE保证失败时数据不半提交——这个顺序不能反先 RAISE 的话 ROLLBACK 就不会执行了。注意FORALL在集合元素为 NULL 时会跳过该行而不报错如果业务上不允许 NULL需要在存储过程里显式判断p_orders(i).order_no IS NULL并抛异常。3. MyBatis 侧怎么把 List 映射成 Oracle 嵌套表3.1 TypeHandler 是绕不开的一环MyBatis 内置的ArrayTypeHandler能处理java.sql.Array但它要求你传的已经是Connection.createArrayOf创建的对象而 Mapper 方法签名里通常是ListOrderRow。所以常见做法是自定义一个TypeHandler在setParameter里把 List 转成java.sql.Array在getResult里做反向转换如果存储过程有 OUT 的数组参数。下面是一个可复用的TypeHandler骨架// 泛型 T 是单行对象类型这里用 OrderRow 示意 MappedTypes(List.class) MappedJdbcTypes(JdbcType.ARRAY) public class OracleListTypeHandler extends BaseTypeHandlerListOrderRow { // Oracle 嵌套表的类型名必须和数据库里建的一致 private static final String ORACLE_TYPE_NAME T_ORDER_TAB; Override public void setNonNullParameter(PreparedStatement ps, int i, ListOrderRow parameter, JdbcType jdbcType) throws SQLException { Connection conn ps.getConnection(); // 把 List 转成 Object[]每个元素是 oracle.sql.STRUCT 或 java.sql.Struct Object[] elements new Object[parameter.size()]; for (int idx 0; idx parameter.size(); idx) { OrderRow row parameter.get(idx); // 用 Connection.createStruct 构造单行结构 elements[idx] conn.createStruct( T_ORDER_ROW, new Object[]{row.getOrderNo(), row.getUserId(), row.getAmount()} ); } // 用 createArrayOf 构造嵌套表 Array array conn.createArrayOf(ORACLE_TYPE_NAME, elements); ps.setArray(i, array); } Override public ListOrderRow getNullableResult(ResultSet rs, String columnName) throws SQLException { // 如果存储过程有 OUT 数组参数在这里反解 Array array rs.getArray(columnName); return array null ? null : convertArray(array); } // 其余 getNullableResult 重载省略逻辑类似 private ListOrderRow convertArray(Array array) throws SQLException { Object[] elements (Object[]) array.getArray(); ListOrderRow result new ArrayList(elements.length); for (Object elem : elements) { Object[] attrs ((Struct) elem).getAttributes(); OrderRow row new OrderRow(); row.setOrderNo((String) attrs[0]); row.setUserId(((Number) attrs[1]).longValue()); row.setAmount(new BigDecimal(attrs[2].toString())); result.add(row); } return result; } }关键点在conn.createStruct和conn.createArrayOf这两步。createStruct的第一个参数是 OBJECT TYPE 名第二个是属性数组顺序必须和 TYPE 定义一致。createArrayOf的第一个参数是 TABLE TYPE 名第二个是元素数组。这两个方法都依赖 JDBC 驱动对 Oracle 类型的支持用 ojdbc8 及以上版本比较稳。3.2 Mapper XML 里 statementType 和 mode 的写法Mapper 接口方法签名// 注意 Param 里的名字要和 XML 中 #{orders, typeHandler...} 对应 int batchInsertOrders(Param(orders) ListOrderRow orders, Param(result) MapString, Object result);XML 映射select idbatchInsertOrders statementTypeCALLABLE parameterTypemap {call P_BATCH_INSERT_ORDER( #{orders, modeIN, jdbcTypeARRAY, typeHandlercom.example.handler.OracleListTypeHandler}, #{result, modeOUT, jdbcTypeNUMERIC} )} /select这里有几个必须注意的点。第一调用存储过程用select标签而不是insert因为statementTypeCALLABLE配合{call ...}语法时MyBatis 走的是CallableStatement用select才能正确拿到 OUT 参数。第二modeIN和modeOUT必须显式写不写的话 MyBatis 默认按 IN 处理OUT 参数拿不到值。第三typeHandler要写全限定类名或者在 MyBatis 配置里注册后简写。第四OUT 参数用Map接收时key 就是#{result}里的result调用后从map.get(result)取值。3.3 调用层代码和事务边界Service 层调用Service public class OrderService { Autowired private OrderMapper orderMapper; Transactional(rollbackFor Exception.class) public int batchInsert(ListOrderRow orders) { // 分批每批 500 条避免单次 ARRAY 过大 int batchSize 500; int total 0; for (int i 0; i orders.size(); i batchSize) { int end Math.min(i batchSize, orders.size()); ListOrderRow sub orders.subList(i, end); MapString, Object result new HashMap(); orderMapper.batchInsertOrders(sub, result); Object cnt result.get(result); if (cnt null || ((Number) cnt).intValue() 0) { throw new RuntimeException(批量插入失败批次起始 i); } total ((Number) cnt).intValue(); } return total; } }分批的原因后面避坑章节会细说这里先记住 500 这个经验值。Transactional保证整批要么全成功要么全回滚但要注意存储过程内部已经COMMIT了外层事务对已提交部分无能为力——这是 Oracle 存储过程和 Spring 事务配合时的经典矛盾。我的做法是存储过程内部不COMMIT把提交权交给 Spring但这样又要求存储过程调用必须在事务内。两种方案各有取舍下面避坑章节展开。4. 参数上限、类型不匹配和事务那些坑4.1 ORA-06550 和 invalid column type 的排查顺序现象调用时报ORA-06550: 第 1 行, 第 7 列: PLS-00306: 调用 P_BATCH_INSERT_ORDER 时参数个数或类型错误或者 JDBC 层直接抛invalid column type。原因通常有三个一是 TYPE 名拼写和数据库里不一致Oracle 默认大写Java 里写小写会找不到二是createStruct的属性个数和 OBJECT TYPE 定义不匹配三是createArrayOf的 TYPE 名不是 TABLE TYPE 而是 OBJECT TYPE。解决先在数据库里执行SELECT * FROM USER_TYPES WHERE TYPE_NAME T_ORDER_TAB确认类型存在且TYpecode是COLLECTION。然后在TypeHandler里打印elements.length和每个Struct的属性个数和 TYPE 定义逐一对齐。最后确认createArrayOf传的是T_ORDER_TAB而不是T_ORDER_ROW。4.2 单次 ARRAY 别超过 1000 条现象批量 5000 条时偶尔成功偶尔报ORA-01460: 未实现或不合理的转换请求或者直接 OOM。原因Oracle 对单个 ARRAY 的大小有隐式限制具体阈值和 JDBC 驱动版本、java.sql.Array实现有关但经验上超过 1000 条就容易出问题。另外createStruct会为每行创建一个对象5000 行就是 5000 个 Struct 对象堆内存压力不小。解决分批每批 500 条。这个值不是拍脑袋是我在几个项目里试出来的平衡点——太小则网络往返次数多太大则内存和驱动层容易出问题。分批逻辑放在 Service 层如上面代码所示。4.3 存储过程 COMMIT 和 Spring 事务的冲突现象Service 方法抛异常期望整批回滚但数据库里已经有一部分数据了。原因存储过程内部写了COMMIT这个提交是数据库层面的不受 Spring 事务管理。Spring 的Transactional只能回滚它自己发起的事务对存储过程内部的提交无能为力。解决两种方案。方案 A存储过程内部不COMMIT由 Spring 统一提交缺点是存储过程单独调用时比如运维手动执行不会自动提交需要调用方自己处理。方案 B存储过程内部COMMITService 层不做事务控制改为在应用层做补偿——失败时记录失败批次人工或定时任务重试。我一般选方案 A因为事务边界清晰出问题好排查。4.4 OUT 参数拿不到值的两种常见写法错误现象map.get(result)返回 null。原因一XML 里modeOUT没写MyBatis 按 IN 处理自然不会回填。原因二jdbcType和存储过程 OUT 参数类型不匹配比如存储过程是NUMBERXML 里写了jdbcTypeVARCHAR驱动层转换失败但不报错只是不回填。解决确认 XML 里modeOUT和jdbcType都写对。如果还是 null把 MyBatis 日志级别调到 DEBUG看CallableStatement的registerOutParameter有没有被调用。另外OUT 参数用Map接收时parameterType要写map不能写具体的实体类。4.5 空 List 导致的 ORA-06531现象传入空 List 时存储过程报ORA-06531: 引用未初始化的集合。原因createArrayOf传空数组时Oracle 侧拿到的是一个未初始化的嵌套表p_orders.COUNT会直接抛异常而不是返回 0。解决在TypeHandler里判断 List 为空时不调用createArrayOf而是ps.setNull(i, Types.ARRAY, T_ORDER_TAB)。同时在存储过程开头加IF p_orders IS NULL OR p_orders.COUNT 0 THEN RETURN; END IF;双保险。这个坑我在两个项目里都踩过空集合的处理一定要在 Java 侧和 PL/SQL 侧都做。5. 把批量插入压到一次往返几个能直接抄的优化技巧5.1 用 FORALL 加 SAVE EXCEPTIONS 做部分失败容忍默认的FORALL遇到一行失败就整批回滚。如果业务允许部分成功可以加SAVE EXCEPTIONSDECLARE e_bulk_errors EXCEPTION; PRAGMA EXCEPTION_INIT(e_bulk_errors, -24381); BEGIN FORALL i IN 1 .. p_orders.COUNT SAVE EXCEPTIONS INSERT INTO T_ORDER (order_no, user_id, amount, create_time) VALUES (p_orders(i).order_no, p_orders(i).user_id, p_orders(i).amount, SYSDATE); EXCEPTION WHEN e_bulk_errors THEN -- SQL%BULK_EXCEPTIONS 里记录了失败的行号和错误码 FOR j IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP DBMS_OUTPUT.PUT_LINE(失败行 || SQL%BULK_EXCEPTIONS(j).ERROR_INDEX || 错误码 || SQL%BULK_EXCEPTIONS(j).ERROR_CODE); END LOOP; -- 成功的行已经插入这里可以选择提交或回滚 COMMIT; END;SQL%BULK_EXCEPTIONS是个伪集合ERROR_INDEX对应p_orders里的下标ERROR_CODE是 Oracle 错误码。拿到这些信息后可以回传给 Java 侧做失败明细记录。注意SAVE EXCEPTIONS下成功的行已经插入是否提交取决于业务容忍度。5.2 用 DML 错误日志表替代手动记录如果不想在存储过程里写DBMS_OUTPUT可以建一张错误日志表用LOG ERRORS子句-- 先建错误日志表 BEGIN DBMS_ERRLOG.CREATE_ERROR_LOG(T_ORDER, ERR_T_ORDER); END; / -- FORALL 里加 LOG ERRORS FORALL i IN 1 .. p_orders.COUNT SAVE EXCEPTIONS INSERT INTO T_ORDER (order_no, user_id, amount, create_time) VALUES (p_orders(i).order_no, p_orders(i).user_id, p_orders(i).amount, SYSDATE) LOG ERRORS INTO ERR_T_ORDER (batch_insert) REJECT LIMIT UNLIMITED;失败的行会自动写入ERR_T_ORDER包含错误码、错误信息、行数据。这个方案比手动解析SQL%BULK_EXCEPTIONS更省事适合失败率低但需要留痕的场景。REJECT LIMIT UNLIMITED表示不限制失败行数如果设成具体数字超过后整批回滚。5.3 验证批量插入是否真的生效写完别急着上线用下面这段 SQL 验证-- 查最近一批插入的数据量和时间分布 SELECT COUNT(*) AS cnt, MIN(create_time) AS min_time, MAX(create_time) AS max_time FROM T_ORDER WHERE create_time SYSDATE - 1/24; -- 查错误日志表里有没有残留 SELECT * FROM ERR_T_ORDER WHERE ORA_ERR_TAG$ batch_insert;第一段确认数据确实进去了第二段确认没有静默失败的行。如果ERR_T_ORDER里有数据但业务没感知说明异常处理逻辑有漏洞需要检查SAVE EXCEPTIONS后的提交策略。5.4 一个我常用的参数速查表参数建议值说明单批 List 大小500超过 1000 易触发驱动层问题VARCHAR2 长度目标列长度 20%留余量避免 ORA-06502NUMBER 精度与目标列一致避免隐式转换丢精度FORALL 模式SAVE EXCEPTIONS需要部分成功时用事务提交方Spring 统一提交存储过程内不 COMMITOUT 参数类型与存储过程声明一致不匹配会静默不回填这张表是我几个项目里沉淀下来的默认值具体项目还要根据数据量和驱动版本微调。比如 ojdbc8 和 ojdbc11 对 ARRAY 大小的容忍度就不一样升级驱动后建议重新压测一遍。最后说个习惯每次改完TypeHandler或存储过程我都会先用 10 条、500 条、2000 条三档数据各跑一遍确认小批量正确、中批量性能达标、大批量不 OOM。这个习惯帮我拦住了好几次上线前的隐患。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Ajax异步请求中DOM元素显隐控制的工程实践

Ajax异步请求中DOM元素显隐控制的工程实践

这阵子一直在维护一个后台前端页面,列表筛选、详情弹窗、导出按钮这些交互,全都得等接口回包之后才能决定界面怎么展示。正好JS系列写到第三篇,这次想认真聊一个看起来很小、但实际上很容易翻车的问题:在ajax请求过程中&#xff0…

2026/10/17 21:07:17 阅读更多 →
IndexedDB从入门到实战:打破localStorage容量上限的完整存储方案

IndexedDB从入门到实战:打破localStorage容量上限的完整存储方案

在做数据量比较大的前端项目时,我第一次被 localStorage 的 5MB 上限卡得死死的——几万条业务数据塞进去,还没等序列化完成,浏览器就开始报 QuotaExceededError。后来尝试用内存缓存兜底,又扛不住页面刷新,每次重新进…

2026/10/17 21:07:17 阅读更多 →
色彩命名工具核心算法:Lab空间转换与最近邻匹配实践

色彩命名工具核心算法:Lab空间转换与最近邻匹配实践

如果你在做前端组件库、可视化大屏、无障碍辅助工具,或者任何一个需要“把颜色翻译成人话”的场景,你迟早要面对一个名字叫“色彩命名工具”的小模块。它的活儿很简单:用户从拾色器里拖出一个#3498DB,你要告诉他这叫“天蓝色”而不…

2026/10/17 21:07:17 阅读更多 →

最新新闻

软件交付系统移交清单模版:四字段结构与验收闭环实现

软件交付系统移交清单模版:四字段结构与验收闭环实现

简介:这份《软件交付系统移交清单模版》面向软件项目经理、交付实施人员与验收对接负责人,用于解决系统上线移交环节内容遗漏、责任不清、文档散乱等问题。模版以项目基本信息、移交类目、软件交付清单、硬件交付清单、项目文档交付清单及其他交付内容为…

2026/10/17 23:30:27 阅读更多 →
CODE V实例:VGA数码相机物镜从规格到像差分析全流程

CODE V实例:VGA数码相机物镜从规格到像差分析全流程

简介:面向光学设计与CODEV初学者的实例型文档,围绕数码相机定焦镜头从规格定义到像差评估的完整流程展开。内容以建立镜头、缩放镜头和查看像差曲线为主线,演示如何利用新镜头向导从专利库中筛选起始点,通过F/#、视场角、元件数范…

2026/10/17 23:30:27 阅读更多 →
AI Agent Harness Engineering 并发控制实战:多任务同时执行下的资源隔离与状态一致性

AI Agent Harness Engineering 并发控制实战:多任务同时执行下的资源隔离与状态一致性

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

2026/10/17 23:30:27 阅读更多 →
如何不破坏已有分片增量扩展数据集:tasksource-jev-typed-decisions 的 WebInstruct 数据追加完整复盘

如何不破坏已有分片增量扩展数据集:tasksource-jev-typed-decisions 的 WebInstruct 数据追加完整复盘

数据集NLP机器学习 【免费下载链接】tasksource-jev-typed-decisions 项目地址: https://ai.gitcode.com/hf_mirrors/tasksource/tasksource-jev-typed-decisions 点击查看 免费下载 你是否想给一个已发布的大数据集"加料",却又怕一动就毁掉已…

2026/10/17 23:30:27 阅读更多 →
SysML不是UML升级版:系统工程建模的范式迁移与元模型本质

SysML不是UML升级版:系统工程建模的范式迁移与元模型本质

简介:本资源是系统工程领域权威入门读物《Systems Engineering with SysML/UML》的完整PDF电子版,面向系统工程师、嵌入式开发人员、MBSE(基于模型的系统工程)实践者及高校相关专业师生,旨在解决复杂系统建模中需求追踪…

2026/10/17 23:30:27 阅读更多 →
加载结果数据的工程化指南:从异步分页到弱网优化

加载结果数据的工程化指南:从异步分页到弱网优化

1. 从一句“加载结果数据”说起的真实场景如果你在代码仓库里翻到一个只有“加载结果数据”六个字的提交记录,第一反应大概率是困惑。这也太模糊了。可真正做过数据处理或者后台管理系统的人都会心一笑——这六个字背后,往往藏着一整套“从数据源取数&am…

2026/10/17 23:29:26 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →