NocoBase Repository create 方法之 CreateOptions 参数完全指南
NocoBase Repository create 方法之 CreateOptions 参数完全指南【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase导读CreateOptions是 NocoBase 数据库层Repository.create()方法的核心参数类型它决定了创建记录时哪些字段可以被写入、哪些关联会被更新、以及在哪个事务中执行。本文基于官方 API 文档结合nocobase/database包的源码实现逐一拆解values、whitelist、blacklist、updateAssociationValues、transaction等参数的类型定义、默认行为与底层原理帮助你在开发插件或扩展时精准控制数据写入。一、CreateOptions 类型定义总览官方文档给出的类型定义位于 create-options.md其核心结构如下type WhiteList string[]; type BlackList string[]; type AssociationKeysToBeUpdate string[]; interface CreateOptions extends SequelizeCreateOptions { values?: Values; whitelist?: WhiteList; blacklist?: BlackList; updateAssociationValues?: AssociationKeysToBeUpdate; context?: any; }需要特别说明的是该接口继承自 Sequelize 的SequelizeCreateOptions因此除了上表列出的 NocoBase 扩展字段外Sequelize 原生支持的transaction、hooks、ignoreDuplicates、returning等选项同样可用。这一点在源码中可以直接验证repository.ts 中定义了CreateOptions其values类型为Values | Values[]支持批量创建relation-repository/types.ts 中关系仓库RelationRepository也复用了完全相同的CreateOptions结构因此本文内容同时适用于RelationRepository系列接口。各参数速览参数类型作用默认行为valuesValues \| Values[]要创建的记录的数据对象必传否则创建空记录whiteliststring[]仅允许写入的字段白名单不传则允许所有字段写入blackliststring[]禁止写入的字段黑名单不传则允许所有字段写入updateAssociationValuesstring[]指定哪些关联键参与更新create 时默认为全部关联transactionTransaction事务对象不传则自动创建内部事务contextany透传给钩子与中间件的上下文无二、values要创建的记录数据values是创建操作的数据主体既可以传入单条记录对象也可以传入对象数组实现批量创建。当传入数组时Repository.create()内部会自动转调createMany()方法这一点在 repository.ts 中有明确实现async create(options: CreateOptions) { if (Array.isArray(options.values)) { return this.createMany({ ...options, records: options.values, }); } // ... }而createMany则是在同一个事务中逐条调用create()完成批量写入见 repository.tsasync createMany(options: CreateManyOptions) { const transaction await this.getTransaction(options); const { records } options; const instances []; for (const values of records) { const instance await this.create({ ...options, values, transaction }); instances.push(instance); } return instances; }实战示例——单条创建const repository db.getRepository(posts); // 单条创建 const post await repository.create({ values: { title: Hello NocoBase, content: This is a test post., }, }); // 批量创建内部转调 createMany const posts await repository.create({ values: [ { title: Post 1, content: ... }, { title: Post 2, content: ... }, ], });值得注意的是values中不仅可以包含普通字段还可以包含关联字段如userId、tags等这部分会在关联更新一节详细展开。三、whitelist 与 blacklist字段写入的门卫whitelist与blacklist用于控制values中哪些字段可以真正写入数据库是构建安全写入逻辑的关键工具。whitelist白名单只允许列表中列出的字段被写入未列出的字段会被丢弃blacklist黑名单禁止列表中列出的字段被写入其余字段正常写入两者都不传时默认允许所有字段写入。底层实现原理字段过滤并非在create()中临时判断而是由独立的UpdateGuard更新守卫类完成其核心是sanitize()方法见 update-guard.ts// handle whitelist if (this.whiteList) { valuesKeys valuesKeys.filter((valueKey) { return ( this.whiteList.findIndex((whiteKey) { const keyPaths whiteKey.split(.); return keyPaths[0] valueKey; }) ! -1 ); }); } // handle blacklist if (this.blackList) { valuesKeys valuesKeys.filter((valueKey) !this.blackList.includes(valueKey)); }从实现上可以提炼出两个关键行为白名单支持点分路径前缀匹配whitelist中的元素形如user.name会以.分割后只取第一段与字段名比较因此whitelist的语义同时约束了顶层字段与嵌套关联字段的写入权限过滤后的值通过lodash.set重新组装最终返回一个只包含允许字段的新对象被过滤的字段不会到达数据库层。另外UpdateGuard还会递归地对关联子对象应用相同的白名单/黑名单逻辑即whitelist中tags.name这样的写法可以精确控制关联记录的字段写入范围。实际调用链在Repository.create()中repository.tsconst guard UpdateGuard.fromOptions(this.model, { ...options, action: create, underscored: this.collection.options.underscored, }); const values (this.model as typeof Model).callSetters(guard.sanitize(options.values || {}), options); this.validate({ values: values as any, operation: create }); const instance await this.model.createany(values, { ...options, transaction });流程为构建守卫 → 净化 values → 数据校验validate→ 调用 Sequelize 底层 create 写入。守卫在写库之前完成字段裁剪确保恶意或多余字段不会落库。实战示例// 只允许写入 titlecontent 会被丢弃 await repository.create({ values: { title: Hello, content: should be dropped, status: draft }, whitelist: [title], }); // 禁止写入 status 字段 await repository.create({ values: { title: Hello, content: ok, status: draft }, blacklist: [status], }); // 白名单同时约束顶层字段与关联字段 await repository.create({ values: { title: Hello, user: { id: 1, nickname: hack }, // nickname 不会被写入 }, whitelist: [title, user.id], });四、updateAssociationValues精确控制关联更新updateAssociationValues的类型为AssociationKeysToBeUpdate即string[]用于指定values中哪些关联键需要被处理。它的语义在 create 与 update 场景下略有不同这一点由 update-guard.ts 中的逻辑体现setAssociationKeysToBeUpdate(associationKeysToBeUpdate: AssociationKeysToBeUpdate) { if (this.action create) { this.associationKeysToBeUpdate associationKeysToBeUpdate?.length ? associationKeysToBeUpdate : Object.keys(this.model.associations); // create 时默认处理全部关联 } else { this.associationKeysToBeUpdate associationKeysToBeUpdate; } }可以推断出的关键规则create 场景下如果不传updateAssociationValues默认会处理模型定义的所有关联Object.keys(this.model.associations)传入了则只处理列表中列出的关联update 场景下默认不处理任何关联必须显式传入需要更新的关联键。该参数与updateAssociations联动当传入updateAssociationValues时update-associations.ts 会开启recursive: true递归更新模式允许对关联记录执行级联的新增、修改或删除。关联更新的底层机制Repository.create()在底层实例创建完成后会调用updateAssociations()见 repository.tsawait updateAssociations(instance, values, { ...options, transaction, });updateAssociations会根据关联类型分发处理update-associations.tsswitch (association.associationType) { case HasOne: case BelongsTo: return updateSingleAssociation(instance, key, value, options); case HasMany: case BelongsToMany: return updateMultipleAssociation(instance, key, value, options); }即HasOne/BelongsTo走单值关联更新直接替换关联记录HasMany/BelongsToMany走多值关联更新可传目标主键数组建立关联或嵌套对象数组新增/更新关联记录。实战示例// 创建文章时同时建立与 user、tags 的关联 const post await repository.create({ values: { title: Hello, user: 1, // BelongsTo传主键即可 tags: [1, 2, 3], // BelongsToMany传主键数组 }, }); // 仅更新 user 关联忽略其他关联键 const post await repository.create({ values: { title: Hello, user: 1, comments: [{ content: nice }], // 由于不在列表中不会被处理 }, updateAssociationValues: [user], });五、transaction事务控制transaction用于指定本次创建操作所在的事务。官方文档明确指出如果不传入事务参数create()会自动创建一个内部事务。这一行为在create()中通过getTransaction()实现并且create()方法本身被transaction()装饰器包裹repository.tstransaction() async create(options: CreateOptions) { // ... const transaction await this.getTransaction(options); // ... }在关联更新环节update-associations.ts同样体现了事务的自动管理let newTransaction false; let transaction options.transaction; if (!transaction) { newTransaction true; transaction await instance.sequelize.transaction(); } try { // ...关联更新逻辑 if (newTransaction) { await transaction.commit(); } } catch (error) { if (newTransaction) { await transaction.rollback(); } throw error; }重要推论当调用方没有传入事务时create()主流程与关联更新共用同一个内部事务任一环节失败都会整体回滚保证数据一致性当调用方传入外部事务时newTransaction为false不会 commit/rollback 外部事务交由调用方统一控制——适合多步操作组合成一个大事务的场景。实战示例// 方式一不传事务自动创建内部事务单次操作 await repository.create({ values: { title: Hello } }); // 方式二手动管理事务组合多个操作 const transaction await db.sequelize.transaction(); try { const post await repository.create({ values: { title: Hello }, transaction, }); await otherRepository.create({ values: { postId: post.id, content: comment }, transaction, }); await transaction.commit(); } catch (error) { await transaction.rollback(); throw error; }六、context上下文透传context用于携带与本次操作相关的自定义上下文信息如当前用户、请求元数据等并透传给钩子函数hooks与关联更新逻辑。它在create()的调用链中被持续传递从create(options)传入this.model.create(values, { ...options, transaction })使 Sequelize 钩子可以访问options.context传入updateAssociations()最终作用于关联记录的更新与afterCreateWithAssociations、afterSaveWithAssociations等事件见 repository.ts。从源码结构看context本身不参与字段过滤或数据转换它是一个透明的透传通道用于在创建链路中共享业务上下文。七、与周边 API 的关系CreateOptions并非孤立存在它在 NocoBase 数据访问层中被广泛复用Repository.create / createMany本文讲解的主入口见 repository.tsRelationRepository 系列belongs-to-many、has-many、has-one等关系仓库的创建操作复用相同的参数结构相关文档可参考 belongs-to-many-repository.md、has-many-repository.md、has-one-repository.mdfirstOrCreate / updateOrCreate这两个方法在内部最终都会调用create()因此同样接受whitelist、blacklist、updateAssociationValues、context等参数见 repository.tsRepository 主文档完整的RepositoryAPI 说明见 repository.md。八、最佳实践小结面向不可信输入时优先使用whitelist相比黑名单防漏的思路白名单只放行更安全——即使values中混入了password、role等敏感字段也会被过滤丢弃白名单可配合关联键点分路径使用如[title, user.id]实现主记录与关联记录字段级别的精细控制create 时善用默认关联更新create 默认会处理所有关联如需只建主记录、不动关联可通过updateAssociationValues: []显式关闭批量创建注意事务边界values传数组时所有记录在同一个事务内串行创建量大时应评估性能并考虑分批提交多步操作务必传入共享事务多个仓库操作组合时传入同一个transaction让回滚边界由你掌控避免部分成功导致的脏数据。通过本文对CreateOptions每个字段的逐一拆解结合 repository.ts、update-guard.ts、update-associations.ts 等源码的印证你现在已经能够精确控制 NocoBase 中记录创建的字段范围、关联行为与事务边界写出既安全又高效的业务数据写入逻辑。【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →