O/RM的优势、缺点和最佳实践

O/RM

Object Relational Mapping,对象关系映射,一般简写为O/RM,或者更常见的ORM,就是数据库里面的一条记录,映射到一个对象,记录里面的字段,成为对象的属性。这是面向对象的数据访问方式。

在没有O/RM之前,我们习惯使用代码生成器来根据表结构自动生成各种CRUD(增删查改)方法。但是,这只能满足简单的操作,当业务复杂起来,特别是关系型数据,这个方法捉襟见肘。

不同的技术栈有不同O/RM方案,譬如Python的SQLAlchemy、Java的JPA(Java Persistence API)这个O/RM标准接口的就有多个解决方案。.NET下有从Java的Hibernate移植过来的NHibernate、微软开源的Entity Framework(EF)、Dapper、PetaPoco等。说起Hibernate,几年前12306售票系统出现问题,说是用的Hibernate。

Jeff Atwood是计算机编程博客Coding Horror的博主。他共同创建了计算机编程问答网站Stack Overflow,并共同创建了Stack Exchange。他曾经说过“O/RM是计算机科学的越南战争”

优势

生产力的提高

  • 用更少的代码,简便地实现CRUD(增删查改)
  • 多表连接可以方便地使用对象关系方式访问因为是面向对象,编译时便可知道一些用纯SQL可能会遇到的拼写、语法错误。这个有点像TypeScript和JavaScript的关系
  • 在Visual Studio等IDE中,在进行调试的时候,方便地浏览关系型对象因为最终执行的SQL是自动生成的,所以不受代码风格约束,而且只要合理使用O/RM,类似SQL注入等容易在手写SQL遇到的,不是一个大问题
  • 因为数据抽象访问,所以带来了支持多种数据库的可能性,譬如从PostgreSQL切换到SQL Server

缓存:双刃剑

  • 优秀/流行的O/RM内置了对缓存的支持,这样可以减少重复的数据库访问
  • 但是,一些时候你忘记了刷新已经缓存了的对象,你将会遇到数据版本冲突问题(老数据覆盖了较新的数据),一般做法是在必要的地方都调用类似Refresh等方法来刷新,但这样比较蹩脚

缺点

性能约束

  • 初始化加载,视乎你使用Code-first、Model-first还是Database-first,背后在做大量的工作,确保模型映射和数据库架构一致。某司使用NHibernate,几百个model,每次初始化需要3-5分钟
  • N+1问题:父子表关系,映射/使用错误,可能会导致父表的每条记录都会在子表做一次查询,譬如父表有1000条记录,最终可能会产生1001条查询
  • 类似报表中使用的各种聚合、pivoting(行列转换)
  • 要达到理想的性能,你需要调整各种映射属性,甚至做所谓的hacking,譬如模型定义了一些子表关联,如果你不想获取,你可能需要把这些属性设置为空值,或者设置为延迟加载;如果你熟练掌握SQL, 你会发现手写SQL会来得容易很多
  • 批量数据处理:批量导入/更新、导出,真要使用,一般O/RM需要蹩脚的处理

高级功能的缺少/支持

  • 譬如游标、递归、特定类型(如自定义类型)的支持
  • 譬如SQL Server的OUTPUT等的支持
  • 复杂查询,或者一些窗口函数, O/RM要么不支持这意味着你必须传输额外的数据在业务层进行处理,要么会很别扭。这个时候,用存储过程就更加合理

维护的难度

O/RM一个重要的特性,也是必备,就是数据库和对象之间的映射,数据库表、字段的特性,譬如字段的最大长度、各种约束(最大、最小值、默认值等)、精度、外键等,都要一一定义,不管是通过类似Hibernate的XML还是Fluent Hibernate的面向对象方式,或者一些Model-first的通过特性(attribute)来实现。

O/RM的使用,会导致两套数据库结构,一套在数据库里面,一套在O/RM定义。当你需要改动结构,你需要实现迁移,譬如改改变了字段的名字、表名。

使用的成本

使用O/RM的一个目的是只需要关心业务,不需要放多少时间在SQL上面,但是,学习O/RM本身是需要时间的,而且,要用好O/RM,不可避免要学好SQL,所以这个学习时间可能是单纯学习SQL的两倍或者更多。

之前说生产力是O/RM的优势,但是这个是建里在你必须先把映射关系建立好的基础之上,这个过程视乎业务系统的复杂度,需时可能比较长

数据库的表结构很多时候无法和对象模型完整一致,导致了在使用过程中需要做手工的转换,模型也随之快速增大,增加了逻辑的复杂性

之前说O/RM可以切换数据库系统,但是当你把一个数据库系统真的用起来之后,你会发现,你很大机会需要用到数据库系统的一些特性,这是其它数据库系统没有的,那么,这个迁移将会很大的挑战性。越抽象,复杂度越高,成本也随着增加

最佳实践

如果你希望深入了解数据库访问、O/RM最佳实践,跟随有15年+经验的数据库专家手把手、全程实战、系统性地、快速学习和提高数据库开发技术,欢迎访问 DevYeah.com联系我们。

交互式学习平台

本文完整版本在Dev Yeah的交互式学习平台上,有兴趣的同学可以点击这里免费注册,马上免费试用Dev Yeah的各种技术教学视频!

每日技术精选

Dev Yeah推出全新服务:每日技术精选。

不同的技术人有不同的阅读/学习习惯,一些一天读几篇甚至多篇文章,但是:

  • 由于时间限制,花了时间阅读才发现要么文章质量不高或者晦涩难懂,不能高效地学习
  • 日积月累,之前看过喜欢的文章,现在找不回来了

Dev Yeah的每日技术精选,包括但不限于:业界新闻、新/优秀开源项目、优秀技术文章等。分类包括前端、后端、数据存储、安全、AI/大数据等

每天我们会重点对其中一篇内容进行精读概述,让大家能够更好地理解、掌握和提高技术水平。

点击这里免费注册,马上免费试用Dev Yeah的每日技术精选!

Dev Yeah 全栈课程

要系统、快速、全面提高您的技术水平吗?访问Dev Yeah了解我们提供的全栈(前端、后端、数据存储和必备等)Python数据科学课程!15+年全栈开发经验(Web前端、后端、数据库、必备等)的技术专家手把手、全程实战!

扫描下面的二维码加入Dev Yeah技术交流群

扫描下面的二维码联系Dev Yeah客服

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。