V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twogoods
V2EX  ›  数据库

数据库操作你是喜欢 ORM 还是手写 SQL

  •  
  •   twogoods · 2017-09-28 19:58:12 +08:00 · 8942 次点击
    这是一个创建于 2616 天前的主题,其中的信息可能已经有所发展或是发生改变。
    说说为什么?还有可以告诉我哪个语言下哪个库超好用吗?想多了解了解,尝试造个轮子,逃...
    第 1 条附言  ·  2017-09-28 20:43:00 +08:00
    orm 最主要的功能是关系数据映射称为程序中的对象,那类似 hibernate 这种多表,各种关联关系都可以进行映射的功能会用的多吗?动态 sql 需求也是非常常见的,你们怎么处理的,哪个库有比较好的支持?
    111 条回复    2017-11-26 10:29:18 +08:00
    1  2  
    AscenZ
        1
    AscenZ  
       2017-09-28 20:05:04 +08:00
    Golang gorm
    iOS FMDB 有手写 SQL 也有 ORM,Realm 算 ORM 吧
    IllBeBack
        2
    IllBeBack  
       2017-09-28 20:15:39 +08:00
    手写?等注入吗?
    Ison
        3
    Ison  
       2017-09-28 20:18:51 +08:00
    @IllBeBack 被注入不是因为手写 而是因为没有手写好...
    eslizn
        4
    eslizn  
       2017-09-28 20:20:13 +08:00
    工作基本手写,有性能要求并且受限于基础环境。
    自己的业余项目基本用 orm,eloquent 是个不错的 orm 库
    twogoods
        5
    twogoods  
    OP
       2017-09-28 20:21:10 +08:00 via Android
    @IllBeBack 手写也是带 ? 这种预编译 SQL 啊
    w7938940
        6
    w7938940  
       2017-09-28 20:22:18 +08:00
    不会手写,只会 ORM
    undercloud
        7
    undercloud  
       2017-09-28 20:31:40 +08:00
    一般都用 ORM,构建灵活、底层无关,还有比较方便的防注入
    只有在速度有要求,没法优化的情况下才会选择手动构建 sql
    misaka19000
        8
    misaka19000  
       2017-09-28 20:33:30 +08:00
    很烦 orm,喜欢手写
    zonghua
        9
    zonghua  
       2017-09-28 20:36:13 +08:00
    逐渐少用 MyBatis,微服务不需要复杂查询,使用 Criteria
    jtsai
        10
    jtsai  
       2017-09-28 20:37:04 +08:00 via Android
    自己一般手写,工作看情况
    keysona
        11
    keysona  
       2017-09-28 20:38:13 +08:00
    开始都会用 orm,最后又会用到手写。
    lslqtz
        12
    lslqtz  
       2017-09-28 20:40:29 +08:00
    手写
    Miy4mori
        13
    Miy4mori  
       2017-09-28 20:44:52 +08:00 via iPhone
    不喜欢手写 sql,很割裂,不够 oo
    zhustec
        14
    zhustec  
       2017-09-28 20:51:13 +08:00 via Android
    难道不是 Active record 吗
    IllBeBack
        15
    IllBeBack  
       2017-09-28 20:51:40 +08:00
    @Ison 你能保证自己手写没有问题,能保证猪队友的水平吗?再说同样的防注入每次都要做,为什么不用封装好的 ORM?
    a87150
        16
    a87150  
       2017-09-28 21:04:50 +08:00
    ORM 不如手写灵活,但是很方便。
    cholerae
        17
    cholerae  
       2017-09-28 21:05:21 +08:00
    为啥要手写?手写有啥好处吗
    sfree2005
        18
    sfree2005  
       2017-09-28 21:10:20 +08:00 via Android
    当然看需求。当下大部分的操作,ORM 已经做得很好,只有在一些很复杂的操作的时候会手写。
    Actrace
        19
    Actrace  
       2017-09-28 21:13:40 +08:00
    ORM 的本质就是常用操作的 SQL 封装。

    我觉得常用 SQL 操作都应该封装好,这就牵扯到一种 Model 的概念,在我的项目中,Model 只负责处理数据库操作。
    ebony0319
        20
    ebony0319  
       2017-09-28 21:17:44 +08:00 via Android
    面向数据库编程。
    ericls
        21
    ericls  
       2017-09-28 21:19:36 +08:00
    DSL -> ORM -> 手写
    u5f20u98de
        22
    u5f20u98de  
       2017-09-28 21:28:04 +08:00
    手写见过写出注入的,用 ORM 也见过用出注入的,总之变量不绑定好了都会处注入。
    不过遇到的手写出注入的多一些。
    aljun
        23
    aljun  
       2017-09-28 21:37:05 +08:00
    @cholerae 你都手写数据库了,别虐我们了
    Sapp
        24
    Sapp  
       2017-09-28 22:04:55 +08:00
    beego 用的 orm 感觉还可以,但是偶尔还是手写。
    iRiven
        25
    iRiven  
       2017-09-28 22:13:51 +08:00 via iPad
    手写 感觉 sql 就是艺术
    gdtv
        26
    gdtv  
       2017-09-28 22:14:57 +08:00
    我喜欢手写
    gefangshuai
        27
    gefangshuai  
       2017-09-28 22:47:52 +08:00 via iPhone
    我喜欢 no sql
    ZXCDFGTYU
        28
    ZXCDFGTYU  
       2017-09-28 22:47:59 +08:00 via iPad
    一般来说 ORM 大部分都是支持直接 query/execute sql 的,并且大部分也都支持 bind。我的 php 项目用的是 phalcon 框架,其中自带的 query/execute 方法可以直接 push sql 过去,其中 placeholder 就是用来绑定变量的。
    Hstar
        29
    Hstar  
       2017-09-28 23:01:16 +08:00
    当然是用 ORM, 按我的理解, ORM 就是帮你生成 SQL 语句的转译器, 所以没有手写能实现但是 ORM 实现不了的情景. 如果遇上个冷门情景没有现成封装好的方法, 那么加一个好了. 手写 SQL 很溜的用 ORM 肯定更没问题.
    WispZhan
        30
    WispZhan  
       2017-09-28 23:05:46 +08:00
    Code First,ORM 优先。目前是 JPA 用的多。 有必要的话会使用混合 MyBatis 和手写存储过程。
    zjsxwc
        31
    zjsxwc  
       2017-09-28 23:14:50 +08:00 via Android
    能 orm 就 orm,好处多多,代码复用方便,ide 自动推导不会犯错,有可以轻松实现大面积魔改, 实在不行才撸 sql
    fxxkgw
        32
    fxxkgw  
       2017-09-28 23:16:54 +08:00 via iPhone
    混着用,关联查询还是手写方便些个人觉得。。
    scnace
        33
    scnace  
       2017-09-28 23:28:47 +08:00 via Android
    不知道大家怎么看代码里的大段的 SQL 一段很长的 SQL 执行一次 跟 短 SQL 执行多次 到底哪个好 感觉长 SQL 就建表时候的功力了…
    simple_plan
        34
    simple_plan  
       2017-09-28 23:34:58 +08:00
    混用 单表 orm 多表关联 sql
    gclove
        35
    gclove  
       2017-09-28 23:35:54 +08:00
    表关联尽量不要用数据库去实现

    尽量 ORM 吧, 我感觉就像用 C 和 用汇编的区别一样
    carlclone
        36
    carlclone  
       2017-09-28 23:44:04 +08:00 via Android
    手写的不是大神就是菜鸟,大部分都是菜鸟,写出一堆没法维护的东西
    EchoUtopia
        37
    EchoUtopia  
       2017-09-28 23:57:16 +08:00 via iPhone
    orm 可以很方便的复用数据对象
    nekuata
        38
    nekuata  
       2017-09-29 00:11:04 +08:00
    MyBatis 不算 ORM 吧? Hibernate 也不推荐手写 SQL 而是 HQL

    MyBatis & SQL 混用+1
    incompatible
        39
    incompatible  
       2017-09-29 00:23:56 +08:00
    @IllBeBack 什么叫“防注入每次都要做“? 写 sql 时用?而不是直接拼 where 条件这是基本功好伐?
    andrewpsy
        40
    andrewpsy  
       2017-09-29 00:37:10 +08:00
    嫌弃手写的应该都是不怎么写测试的。
    我喜欢手写的性能。如果怕哪块手写的 SQL 不好维护,就加上些自动测试代码,性能安全妥妥的。
    lightening
        41
    lightening  
       2017-09-29 01:06:21 +08:00
    绝大多数情况下用 ORM,需要手写的情况在我职业生涯中应该不超过五次。
    手写的维护起来太困难,毕竟写代码的第一目的是可工作,其次是可维护。

    ORM 的典范我认为是 Ruby 的 ActiveRecord。
    scnace
        42
    scnace  
       2017-09-29 01:34:18 +08:00 via Android
    EricCartman
        43
    EricCartman  
       2017-09-29 02:11:42 +08:00 via Android
    能 ORM 就 ORM,可维护性太重要
    hooopo
        44
    hooopo  
       2017-09-29 02:43:37 +08:00
    OLTP 系统当然 ORM 啦,OLAP 和数据处理相关就手写咯
    msg7086
        45
    msg7086  
       2017-09-29 04:25:11 +08:00   ❤️ 1
    同推 Rails 的 Active Record。

    随便贴一段 ORM 中保存前验证的代码感受下。

    before_save :check_rules
    def check_rules
      conflicts = port_forward_rules.where(exposed_ip: exposed_ip, exposed_port: exposed_port).where.not(id: id)

     # "UDP" only conflicts with "UDP" and "Both"
      if udp?
       conflicts = conflicts.where(protocol: [:udp, :both])
     # "TCP" family never conflicts with "UDP"
      elsif !both?
       conflicts = conflicts.where.not(protocol: :udp)
      end
     
     # No conflicts at all? Great!
      return if conflicts.empty?

      conflict = conflicts.first

     # If they are both HTTP or both HTTPS rule.
      return if ( http? || https?) && conflict.protocol == protocol

      throw(:abort)
    end
    askfilm
        46
    askfilm  
       2017-09-29 08:25:57 +08:00
    php + doctrine 带你飞
    jy02201949
        47
    jy02201949  
       2017-09-29 08:53:43 +08:00
    手写
    blackshadow
        48
    blackshadow  
       2017-09-29 08:57:56 +08:00
    手写 sql
    taomk
        49
    taomk  
       2017-09-29 08:59:07 +08:00 via iPhone
    spring data jpa 基本上只需要继承一下框架提供的模版就可以解决所有的数据库基本操作
    nullcc
        50
    nullcc  
       2017-09-29 09:00:59 +08:00
    简单查询 ORM,复杂查询手写
    TangMonk
        51
    TangMonk  
       2017-09-29 09:18:03 +08:00
    ActiveRecord +1
    jjianwen68
        52
    jjianwen68  
       2017-09-29 09:31:46 +08:00
    用 jpa/hibernate,但只做基本方式的映射,不习惯多表关联,复杂一点的查询就直接 hql 或者原生 sql
    CuminLo
        53
    CuminLo  
       2017-09-29 09:35:27 +08:00
    喜欢手写 SQL,但是必须绑定参数来查询。
    至于为什么,可能是之前受过重构的伤,老项目迁移到新框架那些 ORM 迁移,现在想想都心累.....
    linxl
        54
    linxl  
       2017-09-29 09:38:24 +08:00
    laravel eloquent 蛮爽
    Hozzz
        55
    Hozzz  
       2017-09-29 09:41:03 +08:00
    @IllBeBack 手写和注入有什么关系?注入不应该是在连接数据库之前清理的?
    assad
        56
    assad  
       2017-09-29 09:58:51 +08:00
    @askfilm doctrine 用起来啰里八嗦,还不如 illuminate 的呢
    baoanlol
        57
    baoanlol  
       2017-09-29 10:00:43 +08:00
    用过 hibernate,不好用,后来用 slick,喜欢。。。
    ybh37
        58
    ybh37  
       2017-09-29 10:00:49 +08:00
    还是要看具体的业务场景,如果是实体关系简单的业务,ORM 就很好用。
    相反,以下十分复杂的而且对性能有要求,一般会选择 SQL SP
    timwei
        59
    timwei  
       2017-09-29 10:01:02 +08:00
    @msg7086

    只是做字段筛选为什么用了 conflicts = conflicts.where(protocol: [:udp, :both])
    而不用 conflicts = conflicts.select{|t| [:udp, :both].include? t.protocol }

    where 方法会多刷了一次 query 呢
    resturlaub
        60
    resturlaub  
       2017-09-29 10:08:45 +08:00
    直接用 sql 或是用 ActiveRecord 应当是思维上的区别吧。

    用 sql 的时候思考的是用一个语句得到数据,之后不管是把数据转成对象还是直接当数据来用,取数据的过程就是类似于面向过程的思维方式。

    用 ActiveRecord 则全然不是这种思维方式,而是将一个数据表理解成一个类,从中抽出许多对象,得益于此一个对象的属性还可以是其他类型的,如数组,而用 sql 语句的话在存储前和读取后还需要转化,还有其他 enum 等等的特性。
    还有就是代码容易读,比如用 sql status = 1 这是为什么就比较难理解。

    用好 ActiveRecord 还是需要能够很好的理解 sql,这样才能理解迭代器啦,lazy load 在 ActiveRecord 是怎么实现的,才能在使用 ActiveRecord 是不会出现性能差的问题,而且用 ActiveRecord 可以更加良好的封装,同样的语句可以较好的使用数据库的缓存,也便于理解。

    用 rails 之前特别喜欢写 sql,感觉写出一个高性能的 sql 内心十分之爽,后来用了 rails,使用 ActiveRecord 的同时内心还是同时想着形成的 sql 是怎么样的情况,同时也会学习到 ActiveRecord 处理后的生成的 sql 可能比我以前手写的 sql 更为好。

    至于哪个好,我个人觉得这两都是基本功吧,没有场景讨论哪个好没有任何意义。有时 sql 好,够直接,爽。有时 ActiveRecord 好,易理解,爽。建议都要会。
    zgbgx1
        61
    zgbgx1  
       2017-09-29 10:10:46 +08:00
    性能要求高,还用的是 mysql 这种坑逼数据库的话,还是必须手写 sql
    imherer
        62
    imherer  
       2017-09-29 10:21:05 +08:00
    手写
    testcount
        63
    testcount  
       2017-09-29 10:24:35 +08:00   ❤️ 2
    我对外说的时候写 SQL,自己大部分是用 ORM。
    xiaowangge
        64
    xiaowangge  
       2017-09-29 10:25:10 +08:00
    几乎不用 SQL。

    99%场景用腾讯云的 memcached、redis。游戏行业。
    leekafai
        65
    leekafai  
       2017-09-29 10:26:57 +08:00 via Android
    我自己喜欢手写,因为自己写的自己以后看得懂。
    同理,我因此不喜欢别人手写,因为别人的我怕看不懂
    timwei
        66
    timwei  
       2017-09-29 10:29:45 +08:00
    我也是从 Rails 接触 ORM

    ORM 的确可以让不熟 SQL 语句的我迅速开发数据库逻辑

    可是也有些容易溷淆,大致整理几点:

    1. ORM 方法对语言原生方法
    order <-> sort
    where <-> select

    2. ORM 封装的逻辑,以 ActiveRecord 的关联查询举例
    preload、eager_load、includes 三个方法出来的语句差异很大
    新手时期对使用场景还不熟悉,常常乱

    3. ORM 没封装的 SQL 操作
    像是 ActiveRecord 没封装 bulk insertion (只有一个 delete_all 方法)
    又得依赖三方库


    我认为 ORM 主要的价值在让有一定编程经历,却不熟 SQL 语句的程序员操作数据库

    次价值在数据库换型时,几乎不用更动代码
    SQLite -> MySQL -> PgSQL 只需要切换 ORM 的配置,业务代码不用更改
    justfly
        67
    justfly  
       2017-09-29 10:30:52 +08:00   ❤️ 1
    orm

    在互联网行业 mysql 基本当作持久化的 kv 来用,没有复杂 sql 和关联查询。性能基本不用考虑,绝大多数访问都命中缓存,发生缓存穿透 用 SQL 还是 ORM 基本没啥区别。
    winnie2012
        68
    winnie2012  
       2017-09-29 10:48:13 +08:00
    SQL 不利用重构
    timwei
        69
    timwei  
       2017-09-29 10:52:24 +08:00
    @msg7086

    再提一点

    conflicts = conflicts.where(protocol: [:udp, :both])
    conflict = conflicts.first

    逻辑上会与 conflict.where(protocol: [:udp, :both]).first 一样

    可是产生的 SQL 语句会有差别,前者的语句会缺少 LIMIT
    zpf124
        70
    zpf124  
       2017-09-29 10:54:59 +08:00
    @IllBeBack 可能是语言不同导致了你又这种想法。
    最起码在 java 里 手写也可以 很容易的调用预编译 SQL 去解决参数注入的问题。
    twogoods
        71
    twogoods  
    OP
       2017-09-29 10:55:56 +08:00
    @nekuata mybatis 不算 orm?这个问题大家可以讨论讨论
    togodo
        72
    togodo  
       2017-09-29 10:56:30 +08:00
    小项目手写,大项目 orm
    coolcoffee
        73
    coolcoffee  
       2017-09-29 10:58:31 +08:00
    感觉 orm 更接近自然语言
    qiu0130
        74
    qiu0130  
       2017-09-29 11:03:17 +08:00 via Android
    我们公司的经历,开始 ORM,新项目 自己撸一层参数校验跑 SQL,目前打算改造一下 peewee 重构老项目。
    Technetiumer
        75
    Technetiumer  
       2017-09-29 11:13:20 +08:00 via Android
    感觉 SQL 才更接近自然语言

    一般用查询构造器,部分手写 SQL。

    手写 SQL 比较符合我的直觉,查询构造器 /ORM 可以让你方便的跨数据库。
    zpf124
        76
    zpf124  
       2017-09-29 11:52:22 +08:00
    @twogoods 之前有个类似的讨论,不过像我们这样的闲人不是很多。
    https://www.zhihu.com/question/39454008

    虽然我也更习惯 mybatis 去手写多表联查,但个人觉得 它不算是一个标准的 ORM 框架,功能上它与 ORM 框架可以互相替换。

    因为 我觉得 ORM 框架 顾名思义 对象关系映射框架, 他是用来解决映射的,我只需要操作对象,或者导入的数据,中间的映射应该是这种框架去处理的。 而 mybatis 中间的映射则是我们自己写。
    caoz
        77
    caoz  
       2017-09-29 11:55:47 +08:00   ❤️ 1
    让我没想到的是竟然有这么多人喜欢手写... 别的不知道, 起码在 Python 中 SQLAlchemy 比手写好用太多了, 真心推荐大家来试下~

    当然有时候免不了要手写, 比如现在 SQLAlchemy 还不支持一些 MySQL 中的 JSON 操作, 这时候就得用 SQLAlchey 的 text() 功能结合部分原生 SQL 语句了.
    starvedcat
        78
    starvedcat  
       2017-09-29 12:28:53 +08:00
    二进制程序大家喜欢写高级语言再编译还是手写机器码?请踊跃讨论!
    Vans
        79
    Vans  
       2017-09-29 12:32:26 +08:00
    手活好当然要手写了!
    ospider
        80
    ospider  
       2017-09-29 12:35:03 +08:00
    django...
    bzzhou
        81
    bzzhou  
       2017-09-29 12:45:00 +08:00
    ORM,写出来的语法比 SQL 漂亮
    msg7086
        82
    msg7086  
       2017-09-29 13:01:08 +08:00   ❤️ 1
    @timwei
    我这么问你吧。
    1. 你知道 conflicts = conflicts.where(protocol: [:udp, :both]) 这里返回的 conflicts 的类型是什么吗?
    2. 你知道上面代码最差的条件路径下会执行几次 SQL 语句吗?
    msg7086
        83
    msg7086  
       2017-09-29 13:06:56 +08:00   ❤️ 1
    @timwei 上面代码里的确有个可以优化的点,那就是 return if empty?应该改成在 first 之后 return unless conflict。
    wekw
        84
    wekw  
       2017-09-29 13:18:37 +08:00
    ORM 可以大幅提升代码质量,甚至直接把 M 层归零。如果你能理解这句话,恭喜你拿到了高级 web 程序员的入场券。
    tabris17
        85
    tabris17  
       2017-09-29 14:15:44 +08:00
    GraphQL
    tabris17
        86
    tabris17  
       2017-09-29 14:17:31 +08:00
    用 ORM/ActiceRecord 解决 99%的业务,剩下 1%可以使用原生 SQL
    codeyung
        87
    codeyung  
       2017-09-29 14:22:33 +08:00
    手写
    honkew
        88
    honkew  
       2017-09-29 14:35:30 +08:00
    ORM 做不到的就手写
    evlos
        89
    evlos  
       2017-09-29 14:41:25 +08:00
    以前坚持手写了几年,后来只有在联合查询的时候部分手写,大部分用 ORM
    shakoon
        90
    shakoon  
       2017-09-29 14:45:04 +08:00
    手写了十多年 SQL,表示很顺手,没有改变的动力
    greatghoul
        91
    greatghoul  
       2017-09-29 14:48:01 +08:00 via Android
    都喜欢
    thisisgpy
        92
    thisisgpy  
       2017-09-29 15:03:21 +08:00
    Java。我一直用 mybatis 手写 SQL,我承认,我优化不好 ORM,所以选择手写。
    timwei
        93
    timwei  
       2017-09-29 15:48:01 +08:00 via Android
    @msg7086

    这检查方法内 conflicts 只用来产生 conflict 做检查

    1. 所以用 where 回传 relation,或是用 select 回传 array 都能做到

    用 where 还多一次查询。


    2. 这个检查方法会增加两次查询,分别是 line3 where/where.not 跟 line5 的判断内 where

    而后面说的 first

    是指你其实只用了 conflicts 第一个元素,应将 line14 的 first 加在 line5 的 where 后

    让你的查询多了 LIMIT 只返回第一个记录或 nil,而不是传回含 N 条记录的 relation 再取第一条记录
    jydeng
        94
    jydeng  
       2017-09-29 15:53:20 +08:00
    一直手写,有时候觉得烦
    zhouyou457
        95
    zhouyou457  
       2017-09-29 16:12:39 +08:00
    最开始编程的时候都是手写,后面发现维护起来太痛苦,而且也无法做到数据库的无缝切换。后来,老大在 spring jdbc 上简单的封装了一层,然后使用代码生成器生成代码,感觉很爽,但是复杂逻辑还是要手写。。现在使用 mybatis,能用三方库实现的功能绝对不手写,复杂逻辑写到数据库视图中,mybatis 的 xml 现在看着非常简洁。。说实话,还是得看项目情况和人员配置,如果项目急,人员都是新手,那还是别手写了,影响项目进度。
    ljh0585
        96
    ljh0585  
       2017-09-29 17:08:11 +08:00
    一般跟团队。。
    团队走 ORM 那就用 ORM,团队都手写那就大家都手写呗。
    ss0xt
        97
    ss0xt  
       2017-09-29 17:11:06 +08:00
    嗯 键盘敲,不手写(滑稽
    monsterxx03
        98
    monsterxx03  
       2017-09-29 18:06:09 +08:00
    以前都是 orm, 后来全手写, orm 隐藏了太多细节, 调优的时候很痛苦, 怕手写出注入的,基本用 orm 也能用出注入来.
    aa23
        99
    aa23  
       2017-09-29 18:22:30 +08:00
    我喜欢用存储过程
    dremy
        100
    dremy  
       2017-09-29 18:34:43 +08:00 via Android
    手写 SQL 一时爽,重构火葬场
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5966 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 06:10 · PVG 14:10 · LAX 22:10 · JFK 01:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.