在Nodejs生态中,Prisma是一个非常流行的ORM库,支持Typescript,提供了非常友好的类型推断能力。但是,Prisma却不能优雅的支持DTO。在与其他后端框架整合时,DTO是进行参数验证、生成Swagger元数据的关键节点。如果不能像推断类型一样自动推断出DTO,那么,我们就仍然需要手工创建DTO。随着业务的增长,复杂的表间关系会让手工补充DTO的工作日益繁重。

而Vona ORM就提供了非常便利的工具,使我们可以非常直观的动态推断出DTO,就像推断类型一样,从而解放我们的双手,显著提升生产力。甚至可以说,能够自动推断DTO,为Nodejs后端框架打开了一扇窗。

Vona本身就是一款更直观的Nodejs框架,如果大家第一次接触,可以先参考这篇文章:你认为Vonajs提供的这些特性会比Nestjs更好用吗?

限于篇幅,这里不展开讲解Vona ORM所有的知识点,而是以目录树为例,演示如何查询一棵目录树,以及如何动态生成DTO,并最终生成Swagger元数据。Vona框架作者正在直播撰写Vona文档。围观官方文档的实时编写过程,有利于加深对框架设计的理解,探索不一样的架构设计路径。有兴趣的欢迎移步:B站濮水代码直播间

1. 创建Entity

在VSCode中,可以通过右键菜单Vona Create/Entity创建Entity的代码骨架:

@Entity('demoStudentCategory')
export class EntityCategory extends EntityBase {
@Api.field()
name: string; @Api.field(v.optional())
categoryIdParent?: TableIdentity;
}
  • 行2: 继承自EntityBase,就会自动提供5个基础字段:id、createdAt、updatedAt、deleted、iid

    • iid:是实例Id,通过多实例的机制支持多租户系统的开发
  • 行4、7: 定义两个业务字段:name、categoryIdParent
  • @Api.field:通过此装饰器定义的信息,可同时应用于参数验证和Swagger元数据
  • v.optional:声明为可选字段
  • 更多信息,参见:Vona Entity

2. 创建Model

在VSCode中,可以通过右键菜单Vona Create/Model创建Model的代码骨架:

import { EntityCategory } from '../entity/category.ts';

@Model({ entity: EntityCategory })
export class ModelCategory extends BeanModelBase<EntityCategory> {}
  • 行3: entity:指定Model所对应的Entity
  • 行4: 继承自BeanModelBase,从而拥有大量操作数据库的方法,如:CRUD、聚合、分组,等等

3. 创建树形结构

如果要创建一棵目录树,本质就是建立Model引用自身的递归结构。Vona ORM同样支持4种关系:1对11对多多对1多对多。那么,在这里,我们就需要采用1对多来创建目录的自身引用关系。

import { EntityCategory } from '../entity/category.ts';

@Model({
entity: EntityCategory,
+ relations: {
+ children: $relation.hasMany(() => ModelCategory, 'categoryIdParent', {
+ autoload: true,
+ columns: ['id', 'name'],
+ }),
+ },
})
export class ModelCategory extends BeanModelBase<EntityCategory> {}
  • 行5: relations:可以定义多个关系
  • 行6: children:定义一个1对多的关系
  • $relation.hasMany:
    • 参数1: 引用自身ModelCategory
    • 参数2: 设置关联外键categoryIdParent
    • 参数3: 关联选项
      • autoload:是否自动加载关联数据
      • columns:控制关联数据的字段列表

4. 创建Controller

在VSCode中,可以通过右键菜单Vona Create/Controller创建Controller的代码骨架:

@Controller()
export class ControllerCategory extends BeanBase {}

接下来我们创建一个Api,用于获取目录树:

export class ControllerCategory extends BeanBase {
@Web.get('getCategoryTree')
async getCategoryTree() {
}
}
  • 行2: 通过@Web.get定义一个api,path为getCategoryTree

5. 查询目录树

一般而言,我们还需要创建一个Service,从而实现以下调用链:Controller->Service->Model->操作数据库。为了简化起见,在这里,我们直接在Controller中调用Model方法:

export class ControllerCategory extends BeanBase {
@Web.get('getCategoryTree')
async getCategoryTree() {
const tree = await this.scope.model.category.select({
columns: ['id', 'name'],
});
return tree;
}
}
  • 行4: 通过this.scope取得Category Model,然后调用select方法

    • columns:指定要查询的字段列表

由于前面我们设置children关系为autoload: true,因此,查询结果tree就是一棵完整的目录树。下面我们看一下tree的类型推断效果:

6. 自动推断DTO

现在我们自动推断DTO,并且设为API的返回数据的类型:

export class ControllerCategory extends BeanBase {
@Web.get('getCategoryTree')
+ @Api.body(v.array(v.object($Dto.get(() => ModelCategory, { columns: ['id', 'name'] }))))
async getCategoryTree() {
const tree = await this.scope.model.category.select({
columns: ['id', 'name'],
});
return tree;
}
}
  • 行3: 通过@Api.body定义API返回数据的类型:

    • v.array:定义数组类型
    • v.object:定义对象类型
  • $Dto.get:动态推断DTO
    • 参数1:指定目标Model
    • 参数2:指定选项
      • columns:指定要提取的字段列表

同样,由于前面我们设置children关系为autoload: true,因此,$Dto.get生成的DTO就是一棵完整的目录树。下面我们看一下API的Swagger效果:

从示意图中,我们可以清晰的看到,这棵树引用的children类型是名称为demo-student.entity.category_2c7d642ee581efa300341e343180fbb0ecdc785d的动态Entity的数组,从而形成一种递归的引用关系。

7. 封装DTO

虽然我们已经实现了预期的目标,但是Vona ORM提供的能力还没有结束。我们可以创建一个新的DTO,将前面的代码$Dto.get(() => ModelCategory, { columns: ['id', 'name'] })封装起来,从而用于其他地方:

在VSCode中,可以通过右键菜单Vona Create/Dto创建DTO的代码骨架:

@Dto()
export class DtoCategoryTree {}

然后我们通过继承机制来封装DTO:

@Dto()
export class DtoCategoryTree
+ extends $Dto.get(() => ModelCategory, { columns: ['id', 'name'] }) {}

现在,我们再使用新创建的DTO来改造前面的API代码:

export class ControllerCategory extends BeanBase {
@Web.get('getCategoryTree')
+ @Api.body(v.array(v.object(DtoCategoryTree)))
+ async getCategoryTree(): Promise<DtoCategoryTree[]>{
const tree = await this.scope.model.category.select({
columns: ['id', 'name'],
});
return tree;
}
}
  • 行3: 直接传入DtoCategoryTree
  • 行4: 返回类型为Promise<DtoCategoryTree[]>

结语

Vonajs已开源:https://github.com/vonajs/vona

Vonajs作者正在B站直播撰写技术文档,工作日每晚8:30,欢迎围观:濮水代码直播间

Prisma不能优雅的支持DTO,试试Vona ORM吧的更多相关文章

  1. 让SpringMVC Restful API优雅地支持多版本

    好久没有更新博客,难得有空,记录一下今天写的一个小工具,供有需要的朋友参考. 在移动APP开发中,多版本接口同时存在的情况经常发生,通常接口支持多版本,有以下两种方式: 1.通过不同路径区分不同版本 ...

  2. 如何优雅的将DTO转化成BO

    用于网络传输的对象,我们都认为他们可以当做是DTO对象,DTO为系统与外界交互的模型对象,那么肯定会有一个步骤是将DTO对象转化为BO对象或者是普通的entity对象,让service层去处理. 网上 ...

  3. 使用、支持、帮助Moon.Orm

    1.关于Moon.Orm的说明 1)任何人和组织都可以免费使用该框架;(赞助者提供长期的技术咨询)  微信微信: 2)5.0之前已经全部开源; 3)5.0标准版本目前对参与者开源(看看下面很简单的), ...

  4. 高性能数据导入方案&表过滤器&一对多支持筛选- .NET SqlSugar ORM

    一.数据导入有哪些难题 1.数据分类 你需要将 插入.更新.忽略不计.错误数据 等进么分类汇总,最后返回给客户,如果没有很好的设计想把这些操作一步到位非常的难 2.高性能 对于插入或者更新 肯定不能单 ...

  5. Windows Vista 安装和使用指导 - 停止支持后的几条建议

    简介 曾经被广大网民吐槽的Windows Vista现在已经淡出了人们的视线,但仍有一些朋友想要体验一下这个操作系统.Windows Vista是Windows发展路线上的里程碑,相比之前的Windo ...

  6. Spring Boot 系列:最新版优雅停机详解

    爱生活,爱编码,本文已收录架构技术专栏关注这个喜欢分享的地方. 开源项目: 分布式监控(Gitee GVP最有价值开源项目 ):https://gitee.com/sanjiankethree/cub ...

  7. Kube-OVN1.5.0新版本发布,支持鲲鹏云平台网络平面部署

    近日,Kube-OVN发布了最新的1.5.0版本.自2019年4月开源以来,Kube-OVN经历了15次重要版本迭代,以及社区成立,建设者贡献代码,稳定性测试,国内外用户开始在生产环境中投入使用,企业 ...

  8. 新款 c++ web framework 支持orm http/2

    c++ web framework很少, 随着c++ 热度升温,c++ 在人工智能 自然语言处理 加快应用. 最近一款国产 c++ web framework 问世 写业务速度跟脚步语言一样速度 自带 ...

  9. [开源].NET高性能框架Chloe.ORM-完美支持SQLite

    扯淡 这是一款轻量.高效的.NET C#数据库访问框架(ORM).查询接口借鉴 Linq(但不支持 Linq).借助 lambda 表达式,可以完全用面向对象的方式就能轻松执行多表连接查询.分组查询. ...

  10. General框架如何实现多数据库支持

    关于用C#实现多数据库支持的方式,大家都会多少了解,本文从General框架的开发思路角度详细介绍General框架实现多数据库支持的方式,使更多的人了解General框架的底层实现并得到所需的相关知 ...

随机推荐

  1. 安装Scikit-learn 0.24.2版本

    安装Scikit-learn 0.24.2版本 Anaconda 安装scikit-learn是0.19版本,目前最新版本是0.24.2,之前的版本与现在的版本之间差距还是比较大,因此有必要对scik ...

  2. Solon AI 正试发布(支持 java8+,RAG,MCP)

    Solon AI 正试发布了(版号,随 Solon v3.3.1).历时小半年. 1.简介 Solon AI 是一个 Java AI(智能体) 全场景应用开发框架,提供有丰富的接口能力.主要支持的的智 ...

  3. JAVA经典算法分析

      算法分析是对一个算法需要多少计算时间和存储空间作定量的分析. 算法(Algorithm)是解题的步骤,可以把算法定义成解一确定类问题的任意一种特殊的方法.在计算机科学中,算法要用计算机算法语言描述 ...

  4. CentOS7.* 查询开机启动项

    使用 systemctl list-unit-files 可以查看启动项 左边是服务名称,右边是状态,enabled是开机启动,disabled是开机不启动 过滤查询可以systemctl list- ...

  5. CSP-S 2020模拟训练题1-信友队T4 二维码

    题意简述 有一个初始全白的\(n*m\)大小的二维网格,每次可以选择一行或一列染全白或全黑.问可以通过任意次该操作得到多少不同的网格.答案对998244353取模. 分析 不难发现,无论怎么染色,都不 ...

  6. Centos7.x根分区扩容

    背景说明 我们在部署好的系统中,随着数据的不断增加, 发现根分区频繁出现满载问题,这种情况下,我们需要对根分区进行扩容. 方案说明 • 使用空闲磁盘扩容到根分区 • 使用空闲的分区扩容到根分区 • 使 ...

  7. 主流负载均衡器LVS、Nginx、HAProxy介绍

    一.简单介绍 1.1 LVS LVS是Linux Virtual Server的缩写,意思是Linux虚拟服务器,LVS由用户空间的ipvsadm和内核空间的ipvs组成,ipvsadm用来定义规则, ...

  8. 现在的AI还能写出短剧剧本了?

    本文由 ChatMoney团队出品 现在大家打开抖音.小红书,琳琅满目,目光所能及的都是各种吸精剧情的小短剧,虽然这些短剧的制作成本低,但是作为编剧的要写脚本,可不认为这么容易啊......... 接 ...

  9. 1分钟了解 GPT-1到GPT-3 演化过程

    在研发ChatMoney这款产品的时候,我开始深入研究GPT的诞生,逐记录下来分享给大家. 前言 Generative Pre-trained Transformer(GPT)系列是由OpenAI开发 ...

  10. PVE折腾笔记 (3) 在原QNAP使用的硬盘上创建ZFS

    前言 在经过一番研究后,我决定使用ZFS作为俩机械硬盘的文件系统,本来也可以和QNAP一样直接ext4的,但ZFS比较安全,有自愈功能,可以处理比特位翻转的问题,总之就是好用. 如果追求灵活性可以使用 ...