• 请不要在回答技术问题时复制粘贴 AI 生成的内容
yodhcn
V2EX  ›  程序员

不限编程语言,你认为哪个 ORM 最好用?

  •  2
     
  •   yodhcn ·
    yodhcn · Jul 15, 2022 · 20906 views
    This topic created in 1411 days ago, the information mentioned may be changed or developed.

    用过一段 nodejs 的 prisma,CURD 确实很爽,但麻烦一点的查询就只能手写 SQL 了,因为 prisma 这个框架不提供底层的 query builder ,最后还是换回了 knex 这个 query builder 一把梭。

    我想了解一下其它编程语言都有哪些好用的 ORM ,哪些 feature 让你选择这个 ORM ?

    听说过 laravel 的 Eloquent 很好用,但不知道 php 现在 Type Hints 发展的怎么样,有没有像 typescript 一样被广泛应用,因为现在大部分常用的 npm 包都有官方或第三方 typescript 类型注释支持。

    Supplement 1  ·  Jul 15, 2022
    看到诸位都在复读 Rails ,Google 了一下,这是一个曾经很流行的框架,后面的很多 web 框架都有借鉴它,但在我印象里,至少在国内 ruby 并不流行?
    而且用过了 typescript 后,我现在更偏好 强类型 /有类型注释 的动态语言。
    144 replies    2022-07-22 09:33:38 +08:00
    1  2  
    tairan2006
        101
    tairan2006  
       Jul 16, 2022   ❤️ 1
    这和语言关系太大,rails 肯定是最强的
    Leviathann
        102
    Leviathann  
       Jul 16, 2022 via iPhone
    @mind3x 这个是同步的
    tf2
        103
    tf2  
       Jul 16, 2022
    @mind3x 大佬这一说跟大家整无语了。
    raptor
        104
    raptor  
       Jul 16, 2022
    当然是 SQLAlchemy
    2NUT
        105
    2NUT  
       Jul 16, 2022
    php 的 laravel
    RRRoger
        106
    RRRoger  
       Jul 16, 2022
    odoo orm
    beginor
        107
    beginor  
       Jul 16, 2022
    C# 的 NHibernate ,EFCore 都挺不错的
    beginor
        108
    beginor  
       Jul 16, 2022
    @beginor 应该是 .NET 的 NHibernate 和 EFCore
    msg7086
        109
    msg7086  
       Jul 16, 2022   ❤️ 1
    如果你想玩 Ruby 那就看看 Rails 。如果不玩,那就找个抄得最像的凑合一下。如果没有抄得像的,那就去学 Ruby 和 Rails 然后自己抄一个。
    而且 Ruby 就是强类型有类型注释的动态语言啊?
    fgwmlhdkkkw
        110
    fgwmlhdkkkw  
       Jul 16, 2022
    SQLAlchemy
    Typegoogse
    Rasphino
        111
    Rasphino  
       Jul 16, 2022
    efcore
    iintothewind
        112
    iintothewind  
       Jul 16, 2022   ❤️ 1
    .net linq 是最优雅的吧
    我只看过代码 没用过
    yodhcn
        113
    yodhcn  
    OP
       Jul 16, 2022
    @msg7086 #109 Ruby 原来是强类型的吗?不是和 python 类似的吗?

    另外,我还有几个问题像请教一下:

    你们为啥都在推荐 Rails ?哪些 feature 让你选择了 Rails 和 Ruby ?
    Rails 啥现在没有以前那么热了?感觉国内现在除了 Java 就是 Go
    你的意思是,后来的 web 框架都借鉴 Rails ,但都没抄明白?最后还是没有 Rails 好用?
    clf
        114
    clf  
       Jul 16, 2022
    不限制数据库的话,Mongo SpringBoot Starter 最爽。
    pluvet
        115
    pluvet  
       Jul 16, 2022
    Eloquent
    HarveyZh
        116
    HarveyZh  
       Jul 16, 2022
    kotlin 的 ktorm,比我现在用的 gorm 好用太多了 https://www.ktorm.org/zh-cn/
    TWorldIsNButThis
        117
    TWorldIsNButThis  
       Jul 16, 2022
    看完这贴,还是不知道这些所谓好用的到底是怎么个好用法
    StarkWhite
        118
    StarkWhite  
       Jul 16, 2022   ❤️ 1
    @mind3x 不是我针对谁,我是说所有代码生成的 orm 都是垃圾 /滑稽
    msg7086
        119
    msg7086  
       Jul 16, 2022   ❤️ 1
    @yodhcn #113 是和 Python 类似啊,Python 也是强类型的。
    Rails 的话,首先 Ruby 这门语言的表达能力强,写起来舒服,这个对我是最重要的。我现在所有的项目(除了公司的)都已经用 Ruby 写了,包括平时用的小工具,服务器上的运维脚本,等等。
    其次是 Rails 本身就是追求最佳实践和约定优于配置。学习 Rails 上手做一个 hello world 级别的项目(比如一个简易的博客)基本上只要几十分钟时间,而且只要你跟着 Rails 的教程走,你的项目就会是可维护、可测试的。
    比如说 Rails 的 ORM 有 database migration 机制,数据库结构的变更可以用代码来描述(增加或者删除列,修改类型,等等),然后你部署新版本的时候只要 migrate 一下数据库就会自动执行变更集,不需要手动去管理。
    又比如说 Rails 很容易集成 BDD 测试驱动开发套件(比如 rspec ),你写生产代码的时候可以一并把测试用例写完。对于 Web 项目,你可以一次性把单元测试和功能测试全部搞定,还有 capybara 这种模拟浏览器点击的组件可以用,这些都可以促使程序员去写可维护可测试的代码。

    Rails 好像从来就没在国内热过。
    西方的初创企业会大规模用 Rails ,因为开发实在是太快了。一个点子想出来,一星期时间就可以从头到尾做完上线测试了,并且可以一直持续迭代到你拿到疯投为止,都不太会有很大的瓶颈。
    至于借鉴,我只知道很多框架都或多或少借鉴了一些 Rails 的东西。(当然你也可以说 Rails 之前就有同样风格的框架了,但是我觉得当时没有任何一个框架能像当年 Rails 一样把各种精华都集中到一起去。)

    当然对于陌生人我一般不会推荐学 Ruby 和 Rails ,原因你也说了,在国内太小众了,没有前途。在美国 Ruby 的工作岗位有不少,前段时间我以前从零开始带入门 Ruby 的徒弟告诉我他找到一个挺不错的工作,远程在家办公写 Rails ,一年 15 万美元。国内学 Ruby 和 Rails 的,大都是真的喜欢 Ruby 和 Rails 的人,否则为什么不学 Python Java Go 呢,哪怕 PHP 工作也比 Ruby 多啊。但是尽管如此,学一下 Rails 还是很好的,有很多最佳实践的概念会影响你一生,让你写其他语言的时候也能受益。
    还有一个原因是 Ruby 和 Rails 太容易搞出 black magic 了。black magic 会让你写代码的时候大呼惊奇,但是万一出了问题踩了坑,那就只能一坑到底爬不上来了。这个我下一楼再说。

    很不幸的,我现在工作用的是 Java 8 。我现在还是保持和以前一样的习惯,写项目会写单元测试和功能测试,写组件会更倾向于拆分结构,写接口会尽可能更「人性化」一些,所以学过 Rails 姑且还是有好处的。
    StarkWhite
        120
    StarkWhite  
       Jul 16, 2022
    生成代码一时爽,后期维护火葬场
    msg7086
        121
    msg7086  
       Jul 16, 2022
    接上面一楼,说说 Rails 的 ORM 。
    我用过的 ORM 不多,十几年前还在写 PHP 的时候给公司写过一个简易的称不上 ORM 的查询工具,用来简化一些代码。这里只能简单聊一聊皮毛。

    Rails 的 ORM 查询器有很多的黑科技。比如说你从表里查数据的时候写条件,在代码里可以把多个条件拆开成多个语句去写,而不是一次写完整。所以你可以这样写:
    p = Post.all
    p = p.where(user_id: uid) if uid != nil
    p = p.where(forum_id: fid) if fid != nil
    p = p.where(created_by: (7.days.ago)..) if show_recent?
    p = p.order(order_by) if order_by != nil
    @ posts = p.page(page)
    另外,从例子里你也可以看出,不仅有 7.days.ago 这样的表达( 7.days 是 Integer 上重载的一个方法,返回一个 Duration ; 7.days.ago 是 Duration 上的一个方法,返回一个带时区的 Time ),有 x.. 这样从 x 到无穷大的 Range 类型,还有 Relation.page 这样利用 kaminari 插件实现的无痛分页组件。

    对于不熟悉这套系统的人来说,只能是看得一头雾水吧。但是如果你很喜欢这种「 black magic 」式的设计,你就会觉得特别爽……

    就说这些吧,说得多了会被人骂的。
    yodhcn
        122
    yodhcn  
    OP
       Jul 16, 2022
    @msg7086 #119 感谢老哥用心的回复!

    我可能搞混了“强类型”和“静态类型”的概念,我还是认为像 TypeScript 这种看一眼函数签名,就能清楚返回值类型,更有安全感。

    而且我也看了 ruby 官网的入门教程,ruby 的类都可以在运行时动态修改,这么灵活的语言,在维护项目代码时不会麻烦吗?不禁让人产生这样的疑问,因为我体验过 python ,过于自由的编程语言,代码质量主要看人,不同开发者写的代码一个天上一个地下,两极分化严重。

    另外我也注意到了 https://github.com/ruby/rbs 与 TypeScript 以及 Python 的 Type Hint 类似,都是通过类型注释实现接近静态类型的体验。TypeScript 现在用的人很多,而且提供了用 .d.ts 声明文件这一方式,让老旧的包也能用上类型注释。但现在的 ruby 社区好像还没怎么普及 rbs 的样子。
    msg7086
        123
    msg7086  
       Jul 16, 2022
    @yodhcn Ruby 和 Python 的巨大区别就是 Python 环境更期待人们有较少的自由,而 Ruby 则给予人们很多的自由。Python 的理念是做一种事应该只有一种最好的做法,而 Ruby 的理念是做一种事应该有很多种做法。Python 其实已经很「死板」了,用 Python 搞 black magic 我的确也见过(我之前重写我司的一个项目就碰到了一个放飞自我的 Python 模块),但是很少很少,基本可以保证写了三五个月的新手和写了三五年的老手能写出差不太多的代码。Ruby 就没这个可能了,写三年和写五年都能差很多,甚至你拿到自己两三年前写的代码都能恨不得重写一遍,因为你现在已经可以用更 magic 的做法来重构了。(在我自己身上已经发生过很多次了,越写越花哨,越写越 magic……

    Rails 现在就是通过半强迫性地促使你写测试代码来保证可维护性。内部实现可以一团糟,但是有了测试以后,重构甚至重写都不是大事,不满意的地方以后再迭代就行了。

    Ruby 的 Type Hinting 是个新玩意儿,我自己都很少用,一个很大的原因是需求太少,至少我自己很少会遇到 Type Hinting 能改善代码质量或者阅读体验的场景。有很多时候如果需要有 Type Hinting 才能搞懂的话,可能是代码结构设计有问题了,我个人觉得。
    ecnelises
        124
    ecnelises  
       Jul 17, 2022
    Rails 的 ActiveRecord 基本介绍在这里: https://ruby-china.github.io/rails-guides/active_record_querying.html

    其实 Rails 这套 ORM 也不是只能在 Ruby 这种高度灵活的动态语言里才能实现,至少大部分我感觉是可以在元编程和静态反射能力强的静态语言里实现的(比如 Rust ?)。其实写 Rails 的时候感觉这套理念也没有太出奇(毕竟 Active Record 本身其实也是一个设计模式的名字),但用其他框架的时候才意识到原来 ORM 可以做得这么水,哈哈哈。

    其实 ORM 的一大痛点在于它的对象模型和 SQL 基于的关系模型并不兼容。如果放弃用面向对象建模数据库,而是在一个类型系统足够强大的强类型语言里( C++模版?)对关系模型建模,也许是条好出路。
    mmdsun
        125
    mmdsun  
       Jul 17, 2022
    不用说,肯定是 Entity Framework
    无论是创建表,还是查询 API 设计都十分优雅。还有强大的异步支持。

    https://docs.microsoft.com/zh-cn/ef/ef6/querying/
    stevefan1999
        126
    stevefan1999  
       Jul 17, 2022 via Android
    最具生產力: EF Core

    最創新: Exposed https://github.com/JetBrains/Exposed
    MintZX
        127
    MintZX  
       Jul 17, 2022 via iPhone
    ActiveRecord 啊
    ChangJingli
        128
    ChangJingli  
       Jul 17, 2022
    Sequelize
    tinyuu
        129
    tinyuu  
       Jul 17, 2022 via iPhone
    java ebean
    molika
        130
    molika  
       Jul 17, 2022 via iPhone
    hugsql
    alinwu05
        131
    alinwu05  
       Jul 17, 2022
    yii2 的 ActivateRecord 应该是借鉴 Rails , 实在是太好用了,换语言都缺乏动力!
    BlindingDark
        132
    BlindingDark  
       Jul 17, 2022 via Android
    Elixir Ecto!
    fqzz
        133
    fqzz  
       Jul 17, 2022
    没见过比 SQLAlchemy 更容易写复杂查询的 ORM
    PopRain
        134
    PopRain  
       Jul 17, 2022
    EF
    nine
        135
    nine  
       Jul 17, 2022
    @yodhcn

    静态类型检测可以给你安全感,也只是安全感而已。但是无论是静态,还是动态,该考虑的事情一个也跑不了。考虑不到,最后还是要手工处理。

    而静态会让人更死板,更繁琐。动态就简单,比如我查一个 status_id

    @regulates = @regulates.where(status_id: params[:status_id])

    api 可以传过来一个 int 就是
    @regulates.where(status_id: 1)
    也可以直接传一个数组,就是
    @regulates.where(status_id: [1,2,3])

    这都是一些基础用法。

    如果想连表查询就
    ```ruby
    @regulates = @regulates.joins(:business).where("businesses.name like '%#{@business_name}%'")
    ```

    想连一堆的表,输出 json 就直接
    ```ruby
    @regulates = @regulates.as_json({
    include: {
    market: {only: nil , methods: :area_name } ,
    business_owner: {except: :password} ,
    submit_serv_user: {only: :username} ,
    serv_depart: {methods: :parent_tree_names} ,
    } ,
    methods: [:status , :regulate_show_status , :alarm_status ,:regulate_times]
    })
    render json: @regulates
    ```
    inlcude 是关联模型,直接连表查数据。
    only 是只查某些字段。
    except 是除了某些字段,其他都查出来。
    method 是直接调模型的方法,可以用来组合复杂的数据,而不是只查表里的内容。
    而且可以 include 的模型再 include ,无限套娃(当然需要动动脑子,考虑一下性能问题)
    是不是比其他 ORM 强出几(十)条街?


    你真正用了 Rails 就会发现,哪哪都能找出甩其他语言框架几条街特性。
    比如你要 post 一个时间到数据库,你可以'2012/12/12' 也可以'2012 12-12' 也可以 '2012/12/12 18:00:00',随便什么样的格式都可以。这种细节数不胜数。
    你和别人的表结构同步,就需要麻烦一点写 migration ,但是这相当于把数据库表结构严格做了版本控制了。
    而部署上,我目前都不用 docker ,因为 Rails 应用本身就是一键部署的。
    1 git 提交代码
    2 运行 cap production deploy
    3 等待部署结束


    Ruby 在中国不火,主要原因是 3 点
    1 互联网创业大潮时期,在中国 PHP 太火,挤掉市场份额。
    2 然后是平台限定,当时 Windows 下 Ruby 基本没法写,基本都是 Mac ,团队硬件成本投入太高,所以也才有各种仿制品。
    3 Ruby 开发效率太高,当你产出是别人几倍拿的还是同样工资,而维护的业务逻辑大量,要把人累死。投资人不懂,只会觉得是理所应当。


    所以除了真正打算自己赚钱的创业项目,或者写给自己用的项目,基本很少有用 Ruby 的。


    我最早写的是 PHP ,2010 年自己写了一个 PHP 框架,抄袭对象的是某个抄 Rails 的 PHP 框架 QeePHP ,抄他是因为他不维护了。同一时期有大火的 Django 、YII ,Django 压根没考虑数据库表结构版本维护,YII 是比较割裂的,migration 做的很初级。我自己的框架想到了 migration 的思路,但是实在不想去做这些底层的东西,因为我的目标是开发赚钱的应用。后来的 Laravel 基本就是 Rails 的强势 copy ,但是用肯定要用更成熟的原版。

    因为 Ruby 是动态语言,所以写 Rails 你应该写一些测试,来保证程序的健康。但是静态语言也应该写测试啊。

    你又担心,多人协同开发,写的代码相互看不懂。但有没有想过,Ruby 和 Rails 的效率可能让你根本不需要那么多人?我现在手里项目 56 张表,10 万多行代码,前后端一个人。

    而且 Ruby 虽然可以 magic ,但并没有规定你不能用朴素的方式来书写代码。
    相反你可以规定,不让自己 /员工用花里胡哨的方法写代码。因为写的 99%代码都是业务,想花哨也花哨不起来,该是 if else 他就得是 if else 。

    而事实上我们正常只有 hack 第三方包,和写一些工具类的时候才会用元编程。其他代码都是一板一眼的。

    所以,你会发现,为什么 Rails 国内这么小众,但是一提牛逼的框架尤其是 ORM ,都要说 Rails 。因为他就是强啊。
    自己研究代码,强烈建议玩玩 Rails 。自己写项目,强烈推荐使用 Rails 。

    PS:只用来做后端哦,orm 和 API 。Rails 默认前端那套东西很不成熟。老版本配套的 webpacker ( webpack+周边)倒是可以,我自己用 webpacker 和 vue 整合了一套实践还是很不错的,但是还没有时间能分享出来。

    完了,变成安利贴了。逃
    StarkWhite
        136
    StarkWhite  
       Jul 17, 2022
    mybatis 应该算不上 orm 库。。。
    haoliang
        137
    haoliang  
       Jul 18, 2022
    @msg7086 @nine 抱歉直接 @了,能捎带介绍下 ruby 界的 async 生态吗? rails 对 async 的支持如何或者 rails 需要 async 吗?
    msg7086
        138
    msg7086  
       Jul 18, 2022
    @haoliang 不太清楚你说的 async 是哪种 async ?并行计算的话 Ruby 这边应该更偏向于用 Parallel 吧。

    @nine 你这怎么突然就安利起来了→_→
    haoliang
        139
    haoliang  
       Jul 18, 2022
    @msg7086 基于 coroutine 的 concurrency 这种, 针对 io 密集型应用,python 、go 、rust 、zig 这些语言中提供的;找到了这个 actor 模型的得星比较多的 concurrent-ruby ,基于线程池
    > Ruby has a very different runtime so true goroutines are not possible. Instead, a Channel.go method is provided for running a block asynchronously, multiplexed onto a special thread pool reserved just for Channel operations.
    不负责任地说,ruby 是不是在这块掉队了?
    msg7086
        140
    msg7086  
       Jul 19, 2022   ❤️ 1
    @haoliang 可以看看 Fiber 和 EventMachine 。
    async 没有特别激进地实现,我猜是因为 EventMachine 早就已经扎根于各种类库里了,没有动力去实现了吧。就算要用,线程池也已经很方便了。
    yodhcn
        141
    yodhcn  
    OP
       Jul 19, 2022
    @nine #135 谢谢你的安利,我决定玩玩 ruby ,不过你说的“平台限定”我今天就体会到了,跟着官网教程走 https://guides.rubyonrails.org/getting_started.html 上来就踩了一个小坑 https://github.com/tzinfo/tzinfo-data/issues/4#issuecomment-40595115
    nine
        142
    nine  
       Jul 19, 2022   ❤️ 1
    @haoliang
    看的比较迷糊。

    要说类似 JS 的 anync 的话用 EventMachine 很多年了,库都是现成的很成熟,能想到的场景应该都能满足,所以似乎没有什么人炒作。

    说 Actor 模型的话,Ruby 内置的有 Ractor ,单进程跑多核,最新版本我简单测试,效果和 goroutine 一样。不过手上没有真实的生产场景需要 Actor 模型,所以仅限测试。(我能想到的异构计算需求主要还是图形开发)

    PS:不要轻易相信网上的评测,因为 Ruby 版本一直在更新,你看得到的评测有可能已经过时了,有具体需求可以动手试一下

    @msg7086 人生苦短 ^_^
    nine
        143
    nine  
       Jul 19, 2022
    @yodhcn

    愿意折腾的话,可以研究下 WSL https://ruby-china.org/topics/38499

    我写的时候还没有 WSL 2 ,后来因为 WSL1 的 IO 有问题,加上台式机风扇太吵,又换回 Mac 了。
    zbinlin
        144
    zbinlin  
       Jul 22, 2022
    都 100 多条回复了,居然没有提到过 Sequelize 的?楼主不是用 TypeScript 吗?难道也没听过?
    1  2  
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   964 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 86ms · UTC 22:05 · PVG 06:05 · LAX 15:05 · JFK 18:05
    ♥ Do have faith in what you're doing.