如何优雅地操作数据库?ORM了解一下

2021-12-08 16:41:44 浏览数 (1)

写作不易,未经作者允许禁止以任何形式转载!

什么是ORM

img

对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,实现面向对象编程语言中的内存对象与关系型数据库中的业务实体之间的关系映射。这样在我们操作数据库的时候,不再需要和复杂的SQL语句打交道,只需要简单地操作对象的属性和方法就可以直接实现对数据库中对应实体表的CRUD(增删改查)的操作。常见的ORM框架有Node.js 的TypeOrm、Sequlize,Java的Hibernate、Mybatis和Go的Gorm、GoRose等。

  • ORM的方法论基于三个核心原则
    • 简单:以最基本的形式建模数据
    • 传达性:数据库结构被任何人都能理解的语言文档化
    • 精确性:基于数据模型创建正确、标准化的结构

为什么会出现ORM

面向对象编程语言和关系型数据库都是目前最流行的技术,但他们的模型是不一样的。

  • 几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
  • 以 MVC 分层模式为例。Model 作为数据承载实体,在用户界面和业务逻辑层之间,数据以面向对象的形式传递;而当我们需要通过 Controller 分发请求把数据持久化的时候,我们就遇到了内存中的对象如何持久化成关系数据库中存储的一条实际数据记录的问题。
  • 面向对象是从软件工程的基本原则,即封装,继承,多态的基础上发展起来的;而关系型数据库则是从数学理论的基础上发展起来的,两者之间是不匹配的。所有就出现了 ORM 以项目中间件的形式实现数据在不同场景下的数据关系映射。。而对象关系映射就是这样一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。在其基础上诞生很多对象和关系之间的映射框架,也即ORM技术。

ORM的使用 以Sequelize为例

仅示例,更多操作可参考

  • Sequelize 中文文档
    • https://www.sequelize.com.cn/
  • RobinBuschmann/sequelize-typescript
    • https://github.com/RobinBuschmann/sequelize-typescript

Sequelize 是一个基于 Promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能。

Sequelize 遵从 语义版本控制。支持 Node v10 及更高版本以便使用 ES6 功能。

连接数据库

  • 设置使用sequlize插件,并配置要连接的数据库

定义Model

通过面向对象Class 和 关系型数据库的表建立连接 @Column 表示数据库的一列 @PrimaryKey 表示主键

代码语言:javascript复制
import {
  Column,
  Model,
  PrimaryKey,
  Table,
} from '@gulu/sequelize/typescript';

enum GameType {
  micro_game = 'micro_game',
  mobile_game = 'mobile_game',
  micro_app = 'micro_app',
}

@Table({ modelName: 'game', timestamps: false })
export default class GameModel extends Model {
  @PrimaryKey
  @Column
  gameId!: string;
  @Column
  name!: string;
  @Column
  description?: string;
  @Column
  type!: GameType;
  @Column
  icon?: string;
  @Column
  isDelete!: number;
}

操作数据库

通过Model的方法操作数据库

代码语言:javascript复制
import GameModel from '../model/game';

// 游戏列表查询服务
async query() {
  return GameModel.findAll({
    // 去除软删除字段
    attributes: {
      exclude: ['isDelete'],
    },
    // 查询未被软删除的游戏
    where: {
      isDelete: 0,
    },
  });
}

相当于以下SQL语句

代码语言:javascript复制
select gameId, name, description, type, icon from game where isDelete = 0;

当然Sequlize也支持SQL语句查询

代码语言:javascript复制
import GameModel from '../model/game';

// 游戏列表查询服务
async query() {
  return GameModel.sequelize.query(
      'select gameId, name, description, type, icon from game where isDelete = 0',
  );
}

ORM的优缺点

优点

  1. 隐藏了数据访问的细节,“封闭”的通用数据库交互是ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑SQL语句。
  2. 开发效率更高,ORM使我们构造固化数据变得简单易行,在ORM诞生前,我们需要见过我们的对象模型转化为一条一条的SQL语句,通过直连或者是DB helper在关系数据库构造我们的数据库体系。而现在,基本上所有的ORM框架都提供了通过对象模型构造关系数据库结构的功能。
  3. 数据访问更抽象、轻便,支持面向对象封装。数据模型都在一个地方定义,更容易更新和维护,也利于重用代码
  4. ORM有现成的工具,很多功能都可以自动完成,比如数据消毒、预处理、事务等等。
  5. 它迫使你使用MVC架构,ORM就是天然的Model,最终使代码更清晰。
  6. 基于ORM的业务代码比较简单,代码量少,语义性好,容易理解。
  7. 防范SQL注入攻击
  8. 不必编写性能不佳的SQL。

缺点

  1. 无可避免的,自动化意味着映射和关联管理,代价是牺牲性能。现在的各种ORM框架都在尝试使用各种方法来减轻性能上的损失,如懒加载技术、缓存技术等。
  2. 面向对象的查询语言作为一种数据库与对象之间的过渡,虽然隐藏了数据层面的业务抽象,但并不能完全屏蔽数据库层的设计。ORM库也不是轻量级的工具,需要花很多精力学习和设置,无疑将增加学习成本。
  3. ORM难以实现过于复杂的查询。虽然可以实现,但是需要花费很大的代价(性能不如原生SQL)。
  4. 持久化层缺乏弹性,一旦出现业务需求变更,就必须修改持久化层的接口
  5. 持久化层同时与域模型与关系数据库模型绑定,不管域模型还是关系数据库模型发生变化,都要修改持久化层相关程序代码,增加了软件的维护难度。

什么是“持久化” 层

  • 持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
  • 总结:当下ORM的开发模式是主流,提高了代码的封装性和可读性,同时防范了SQL注入攻击。以较小量级的性能损失换来了明显的开发效率提升,明显的性能损失往往存在于复杂的查询,这种情况可以选择使用ORM提供的SQL语句接口进行查询以优化性能。

0 人点赞