浪费了 3 天时间尝试在新项目中使用 prisma,最后还是决定回到 typeorm - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
flyingcrp
V2EX    Node.js

浪费了 3 天时间尝试在新项目中使用 prisma,最后还是决定回到 typeorm

  •  
  •   flyingcrp 147 天前 5046 次点击
    这是一个创建于 147 天前的主题,其中的信息可能已经有所发展或是发生改变。

    兄弟们,prisma 有坑,快跑♀

    • update 没有的数据会直接报错(与数据库行为不一致,心智负担+1),如果硬要用需要用自己包装或拓展,然后调入没有 type 的坑

    https://github.com/prisma/prisma/issues/101421

    https://github.com/prisma/prisma/issues/10142#issuecomment-1835279273

    https://github.com/prisma/prisma/issues/20128

    • 时区的问题,对于查询,写入,始终以 UTC 时区,从而忽略了 db 本身的时区,且 client 无法调整 https://github.com/prisma/prisma/issues/5051

    • model 中的关联关系对于业务侧使用显得特别笨重,比如简单的连表查询,尤其是那种不同业务需要临时或一次性的连表查询需要 Prisma.sql 来进行,如果在复杂则要走 typedsql;但是 typedsql 不支持动态条件,这种场景是业务侧最最最最多的,因此即便就是简单的列表+总条数查询都需要结合 Prisma.sql 来做原生 SQL 的拼接。

    在遇到上面 1,2 的时候硬着头皮继续,但是遇到 3 的时候彻底让我放弃了它。

    提桶跑路了 ♀

    兄弟们,节约时间,原理 prisma

    第 1 条附言    146 天前
    48 条回复    2025-08-05 23:24:35 +08:00
    subframe75361
        1
    subframe75361  
       147 天前 via Android
    试试 kysely ,sql 的写法。或者用更火但 dx 差一些的 drizzle orm
    yaodong0126
        2
    yaodong0126  
       147 天前
    你还真别说,迷信 prisma 的人多的一腿
    ultimate42
        3
    ultimate42  
       147 天前
    我是从 typeorm 转到 prisma 的,prisma 确实有不少痛点,时区,联表查嵌套层级深什么的,但感觉开发体验上,prisma 还是要好一点
    857681664     4
    857681664  
       147 天前
    同样 delete 一个不存在的数据也会报错,官方解决方案说是用 executeRaw..
    qiubaowei
        5
    qiubaowei  
       147 天前
    还好我是守旧派 一直用 sequelize
    flyingcrp
        6
    flyingcrp  
    OP
       147 天前
    @ultimate42 我试了,确实不行。model 中注释都不支持。感觉还是差点意思
    flmn
        7
    flmn  
       147 天前
    drizzle 比较好
    BeautifulSoap
        8
    BeautifulSoap  
       147 天前
    也借地方顺便也让大家避坑一个 ORM:千万不要用 drizzle ,千万不要用 drizzle ,千万不要用 drizzle
    Hbisedm
        9
    Hbisedm  
       147 天前
    drizzle
    asen001
        10
    asen001  
       147 天前
    @BeautifulSoap drizzle 有什么坑,有个私活项目用 drizzle 开发到一半了,别吓我
    SolidZORO
        11
    SolidZORO  
       147 天前
    说一个小众 ORM https://sutando.org/ ,底层是 knex ,进可 ORM ,退可 knex RAW 。

    之所以是说而不是推荐,因为实在太小众,推荐的话实在担不起这个责任,只想让更多人知道它。sutando 作者维护不算积极,total 就两人维护,start 几十,但是手感是我用过所有 ORM 里面最好的,基本上做到了 1:1 对标 Laravel 的 Eloquent ,用起来及其优雅。比堪称是 nodejs 届 Laravel 的 adonisjs 自带强耦合的 lucid 还要想像 Eloquent 。

    y1s1 Node 这边的 ORM 真是烂得可以。drizzle 烂。Prisma 烂,typeORM 烂中烂。

    唯一能打一下的是 sequelize ,的确是可靠了,但是及其嗦,TS 支持太差(我是说第三方,第一份约等于没有),以及无止境的 beta 让人又爱又恨。
    yandif
        12
    yandif  
       147 天前
    @BeautifulSoap 同问有啥坑?
    BeautifulSoap
        13
    BeautifulSoap  
       147 天前
    @asen001 真用了那就用嘛,也不是不能用,反正之前写 drizzle 我是真的火大
    官方文档写得一塌糊涂,看起来很正规但有用的信息基本没多少
    schema 一堆特性不支持,连最基本的 index desc asc, union index 都不支。到最后不光要写 schema 还要自己去写额外的 migration sql
    类型检查基于 schema 定义,如果我 select 的字段里掺杂了动态生成自动的内容(比如 COUNT(*)之类)的话,过类型检查能折腾死人
    执行 raw sql 并且获取到返回值而且要过类型检查比登天都难
    等等等等,反正下次项目里谁跟我说用 drizzle 我跟谁急
    12tall
        14
    12tall  
       147 天前
    knex 应该是用的最舒服的了,虽然只是一个 builder
    shakaraka
        15
    shakaraka  
    PRO
       147 天前
    drizzle +1
    flyingcrp
        16
    flyingcrp  
    OP
       147 天前
    目前应该是在 typeorm 中暂时不打算出去了。
    prisma 在构建和打包时也会有很多问题。不设置 binary 的话会直接多 30M+的大小。很离谱。
    然后里面还有一个奇怪的地方,当前 prisma 已经让用自定义 output 路径去做 client 的引入。
    但是底层似乎有依赖了 prisma ,这个里面有个 public 文件夹,里面全是一些文档还是啥的。也是三十多 M.
    justdoit123
        17
    justdoit123  
       147 天前
    也尝试使用 prisma ,说说我觉得的痛点与疑惑,希望有经验的解答下:

    1. prisma 不生成 class ,如何进一步跟 class-validator 以及 swagger 结合?
    2. 不生成 class ,如果我有很简单的 computed field ,就不知道怎么实现。虽然官方有 [Client extension]( https://www.prisma.io/docs/orm/prisma-client/queries/computed-fields#using-a-prisma-client-extension) 方案,但是 extend 后的 model 类型获取不直接。虽然可以通过类型体操获取。
    3. 个人对滥用 DSL 很反感。DB 的 schema 真的到了需要叠一层 DSL 的程度了吗? 我个人认为还没必要,这样做的收益不高。为了“无缝”切换 DB 类型吗?正常项目开发不会频繁切换 DB 类型,况且也无法做到无缝。 想要降低使用 DB 的门槛吗?熟悉一个 DB 真的是后端的基础门槛,你虽然可以暂时欠着,但是终究要还上,借助 DSL 会很被动,学的都是人家嚼碎了喂你的东西。prisma 用 DSL 描述 schema 的理由,我能想到的唯一理由应该就是他们的野心是实现一个跨语言的 ORM 。
    ByteCat
        18
    ByteCat  
       147 天前
    在用 drizzle ,感觉很爽,可以写类似 sql 的语法,复杂查询很方便
    Hanggi
        19
    Hanggi  
       147 天前   1
    感觉楼主还是对 ts 的编程思想理解和 prisma 的使用方法上...有不一致吧。
    技术选型按自身的理解和喜好来就可以了。

    看看 prisma 自己对 typeorm 的对比,有没有吸引自己转战的特性,
    https://www.prisma.io/docs/orm/more/comparisons/prisma-and-typeorm

    至少目前看来 prisma 是趋势,能早点上手就早收益,用不来也没必要强求,毕竟有那么多人还在宣扬不用 orm ,sql 就应该手写,hhh 。
    https://npmtrends.com/prisma-vs-sequelize-vs-typeorm
    Belmode
        20
    Belmode  
       147 天前
    我就觉得用 Prisma 能省点事,不用写一堆像 TypeOrm 中那样的实体对象,写很多注解
    cutchop
        22
    cutchop  
       146 天前
    typescript 挺好的,不知道为什么 prisma 要发明新的格式
    rocmax
        23
    rocmax  
       146 天前 via Android
    @BeautifulSoap
    1. 文档的问题确实存在,过于简略,需要自己摸索
    2.这些都支持啊,我一看还以为这是以前旧帖子呢。drizzle 基本就是把 ts 翻译成 sql ,这种一个关键字就解决的问题怎么会不支持。没有听说过 union index ,你是指复合索引吗,也支持的啊。union 操作倒是不支持是由于类型推断困难,不重视类型安全的可能会支持。
    3. 类型检查当然要基于 schema 定义了,要不咋办? count (*)可以使用 sql<number>标注类型
    4. 同上,你不给类型标注,数据库返回的是 text ,不得按类型 parse 吗。
    rocmax
        24
    rocmax  
       146 天前 via Android
    @cutchop 跟 drizzle 比起来 prisma 的 schema 确实简单好懂,我一个简单项目 drizzle schema 都快 1000 行了,除了我自己没人能看懂,估计也没人有耐心看完,幸好有 visualizer 。
    rocmax
        25
    rocmax  
       146 天前 via Android
    @justdoit123 是的,比如 golang:

    https://github.com/steebchen/prisma-client-go

    由于 prisma core 从 rust 改回 ts ,被放弃了
    rocmax
        26
    rocmax  
       146 天前
    @BeautifulSoap 对不起,上面说的有误,sql<T>`COUNT(*)`类型标注没有用,需要 mapWith 函数
    k9982874
        27
    k9982874  
       146 天前 via iPad
    用不上那些高大上的 orm 功能,转到了 postgres.is
    楼上推荐的 Kysely ,感觉比较像 gorm ,有空试试
    BeautifulSoap
        28
    BeautifulSoap  
       146 天前
    @rocmax
    2. 你自己试试看 mysql 的 schema 里能不能指定 asc 或者 desc 的 index 吧。postgresql 可以,但是 mysql 不行的。并且 mysql 的复合索引文档里根本找不到怎么用
    4. 这个你自己亲自写一下就知道了。就最简单的用 drizzle 执行 mysql 的 `show tables` 然后解析出所有表格。保证你一写一个不吱声。官方文档里只写了怎么执行 raw sql 但对怎么获取到 raw sql 的返回值只字不提。最后花了 N 久时间才找到解决办法
    rocmax
        29
    rocmax  
       146 天前
    @BeautifulSoap
    https://drizzle.run/nx1z72u347hvkyjd0zspe7ki
    这样如何?
    我司从去年初就全面改用 postgresql 了,确实我说的是 postgresql 的情况。
    mysql 的时期用的是 prisma
    rocmax
        30
    rocmax  
       146 天前
    @BeautifulSoap 我知道为啥对 sql<T>类型标注产生错觉了,好像 COUNT 的返回值类型就是 number ,即便标注了 string 依旧是 number
    https://drizzle.run/lstx39x8scbt8gotd2ndrwhp
    Trim21
        31
    Trim21  
       146 天前
    现在在用 drizzle ,但是感觉维护者对 mysql 相关的特性不太重视 ...
    ratazzi
        32
    ratazzi  
       146 天前
    正在用 prisma 看了这帖子怕了,typeorm 简单试过一下,看到生成的 SQL 之后果断放弃,现在我对 JS 写 CRUD 一点兴趣都没了
    flydogs
        33
    flydogs  
       146 天前 via iPhone
    三天时间不算浪费,至少你知道了不适合你现在这个项目。
    zieglar
        34
    zieglar  
       146 天前
    @justdoit123 #17
    我的做法是新建一个 class 来继承 prisma 对应的实体 class ,在新建的自有 class 的基础上去做各种字段装饰、处理操作
    flyingcrp
        35
    flyingcrp  
    OP
       146 天前
    @Hanggi 我确实有可能没有完全理解 prisma 的设计思想。但在业务侧开发中我提到的那些问题,确实是实打实的极大的降低了开发效率和提高了心智负担。如果所有业务都是 CRUD ,prisma 的设计似乎也完全不考虑要实际开发的便利性。最简单的就是 update,delete 没有的数据会直接 Error ,这就引出了多一层 db 和 prisma 的心智负担。这种负担或者说设计让业务侧失去了便利性; model 的 relations 在实际开发中,尤其是 query 场景就几乎不可能把关系定义的完,也不可能依赖这种形式去定义。
    flyingcrp
        36
    flyingcrp  
    OP
       146 天前
    @flydogs 谢谢大哥,又被安慰到
    justdoit123
        37
    justdoit123  
       146 天前
    @zieglar 那是不是 prisma query 出来的数据,再装载到自己实现的实体 class 上?
    BeautifulSoap
        38
    BeautifulSoap  
       146 天前
    @rocmax 你的这个写法,当用 mysql 的时候将会见到这样一副情景♂



    实际上真正 mysql 下能正常过类型检查并且正确执行的代码差不多这样的,堪称和类型检查还有工具斗智斗勇




    至于动态的 count ,我说的不是这种简单情景,比如我想 select 出一个表所有字段,然后再添加一个 count 或者其他动态字段,我必须在 select 中再手动写一遍所有字段(下图 q )。啥,照着官方文档 ...User 这样写?照着官文档写连类型检查都过不去(下图 q2)



    说真的,用了这么多 typescript 的包,头一次遇到 drizzle 这种无时无刻不在花时间跟类型检查斗智斗勇的包♂
    raphaelsoul
        39
    raphaelsoul  
       146 天前
    不是很喜欢他又自己引入一套 schema 语言 所以尝试了一次就丢弃了。
    rocmax
        40
    rocmax  
       146 天前 via Android
    @BeautifulSoap 这是两个事情,上面那个 sql<T>的类型标注是给 ts 侧看的不负责处理数据,你要根据实际返回的数据格式来标注给 ts ,数据本身是不用处理的。
    下面那个用了 cast 所以没办法推断类型,应该在后面加一个 map With 做处理。
    playground 没有 MySQL ,我有空搭个环境试试。
    rocmax
        41
    rocmax  
       146 天前 via Android
    @BeautifulSoap ...User 不行,需要...getTableColumns(User)
    qingjin
        42
    qingjin  
       146 天前
    还好吧,目前没遇到坑,用的挺香
    BeautifulSoap
        43
    BeautifulSoap  
       146 天前
    @rocmax 主要是 `...User` 这个用法是官方文档就这么写的♂
    https://orm.drizzle.team/docs/select#count

    cast 是我复制错代码了,复制成了上面 Aggregations 部分的内容了。不过问题不大,我想吐槽的点不在 cast 上,还是出在...User 报错上。
    zieglar
        44
    zieglar  
       145 天前
    @justdoit123 #36 可以用自己的实体 class 直接承接
    FlashEcho
        45
    FlashEcho  
       145 天前
    prisma 需要一个二进制文件,感觉特别不好,我试用了一下就转 drizzle 了
    FlashEcho
        46
    FlashEcho  
       145 天前
    @BeautifulSoap #13 虽然我主力用 drizzle ,但是 drizzle 的文档确实很垃圾,而且感觉现在的 LLM 对于 drizzle 的理解不是很好
    ckvv
        47
    ckvv  
       121 天前
    @SolidZORO sequelize beta 用起来感觉挺好的
    zhennann
        48
    zhennann  
       64 天前
    1. Vona ORM 支持“临时或一次性的连表查询”
    2. Vona ORM 支持“自动推断生成 DTO”。Prisma 不能优雅的支持 DTO 。如果不能像推断类型一样自动推断出 DTO ,那么,我们就仍然需要手工创建 DTO 。随着业务的增长,复杂的表间关系会让手工补充 DTO 的工作日益繁重。而 Vona ORM 就解决了这个痛点问题: t/1150216
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2817 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 13:36 PVG 21:36 LAX 06:36 JFK 09:36
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86