当前位置: 首页 > news >正文

gorm源码解析(一):ORM概览

文章目录

    • 什么是ORM
    • 为什么需要ORM框架
    • ORM框架的要素
      • 方言
      • 尽可能提高性能
    • 总结

什么是ORM

ORM(Object-Relational Mapping)是对象关系映射的框架
开发者可以使用熟悉的面向对象方式来操作数据库,而无需直接编写繁琐的SQL语句
具体来说就是ORM框架根据元数据完成以下操作:

  • 执行增删改时完成从对象到sql的转换。例如当用户create一个对象时,ORM框架需要根据该对象,生成一条INSERT的sql
  • 解析查询结果时完成从结果到对象的转换。当从mysql server接收到查询结果时,ORM框架需要将其转换为业务model对象
    在这里插入图片描述

为什么需要ORM框架

试想如果没有ORM框架,用标准库sql.DB操作数据库:
假设有一张简单的user表,有3个字段,idnamenumber

CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(100) NOT NULL DEFAULT '',`number` int NOT NULL DEFAULT '0',PRIMARY KEY (`id`)
) ENGINE=InnoDBDEFAULT CHARSET=utf8mb4

表里有一行数据:

1tom12

要用go原生的sql包查一行记录有以下流程:

  1. 注册db驱动:如果用mysql,匿名import github.com/go-sql-driver/mysql 即可
    1. 该包的init方法会完成mysql驱动的注册
  2. 创建sql.DB实例
  3. 执行sql:调db.QueryContext执行查询操作
  4. 读取查询结果:调rows.Next和rows.Scan,将结果设置操传给rows.Scan的指针中
import ("context""database/sql""fmt"// 注册mysql驱动_ "github.com/go-sql-driver/mysql""testing"
)func TestDB(t *testing.T) {// 初始化sql.DBdb, err := sql.Open("mysql", "账号:密码@(连接地址)/数据库名称")if err != nil {panic(err)}ctx := context.Background()// 执行查询rows, err := db.QueryContext(ctx, "select * from user where id = ?", 1)id := 0name := ""number := 0// 接收查询结果for rows.Next() {rows.Scan(&id, &name, &number)}// 输出:1 tom 12fmt.Println(id, name, number)
}

以上的代码有如下问题:

  1. 需要手写sql,容易出错
    1. 例如容易写错字段名 ,写错关键字。需要真正执行sql时才能发现,go编译器无法发现
  2. 难以重构
    1. 如果要改字段名,需要找到所有出现老字段字段名的地方,一个个改
  3. 重复代码很多,样板代码满天飞,一部分精力花在业务无关的地方
    1. 例如:手动处理结果集时,每次接收查询结果时都要在for循环里先调row.Next,再调row.Scan
  4. 开发效率低:需要自己花时间拼接sql,处理返回结果

而ORM框架可以帮我们解决以上问题
我们看看如果用gorm实现上述的功能应该怎么写:

定义model结构体:

type User struct {  Id     int64  Name   string  Number int64  
}  // 自定义表名  
func (*User) TableName() string {  return "user"  
}

执行查询:

// 初始化grom.DB
db, err := gorm.Open(mysql.Open("账号:密码@(连接地址)/数据库名称"))    
if err != nil {  panic(err)  
}  // 执行查询
var users []User  
err = db.Where(User{  Id: 1,  
}).Find(&users).Error

gorm会将Where方法传入的结构体中,不为零值的字段都解析成等值条件查询,然后将查询结果解析到users变量里,可以说极大提升开发效率

当然用ORM也不全是优点。就性能来说,肯定是直接写sql性能最好
毕竟orm框架执行时,最终还是转化为sql,但中间多经过了对象到sql的转化,性能有损失

但在工程上,性能有时候不是第一优先考虑,而是更关注工程效率

  • 交付效率
  • 后期可维护性

这两点是ORM框架的优势

ORM框架的要素

ORM框架还需要考虑以下要素:

方言

sql有一套标准的规范,但有些db的某些sql功能并没有遵守sql规范,或者说不同db的实现有差别,例如:

  • 引号不同:
    • mysql是 `
    • portgres是 "
  • upsert语法不一样,
    • mysql是INSERT ... ON DUPLICATE KEY UPDATE
    • postgres是 INSERT ON CONFLICT

因此ORM框架为了支持多种db,需要抽象出方言dialector,每个db不同的实现需要调方言完成

尽可能提高性能

ORM框架需要提供较好的性能,例如:

  • 元数据缓存:不是每次执行都要重新从model解析一遍元数据,而是只用解析一次,将解析的结果缓存下来
  • 预编译缓存:一般使用预编译时的流程为;prepare一个stmt,执行sql,然后关闭stmt。但可以在ORM层面提供stmt的缓存,下次遇到相同的sql模板时,直接用预编译好的stmt

总结

本文介绍了什么是ORM框架,以及为什么需要ORM。接下来的文章将进入gorm框架原理和源码解析环节


http://www.mrgr.cn/news/80287.html

相关文章:

  • 谈一谈数据库中索引使用
  • 低通滤波器,高通滤波器,公式
  • ffmpeg和ffplay命令行实战手册
  • PPO系列5 - PPO具体实现
  • 怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
  • 文本编辑器与正则表达式
  • tryhackme——Defensive Security Intro(防御安全简介)
  • opencv小练习(未完成版)
  • google 的guava 学习 基本工具类
  • WPF 相比 winform 的优势
  • 一、windows上配置ninja环境
  • Leetcode 面试150题 399.除法求值
  • Windows 系统下 Python 环境安装
  • Ansible自动化运维(五) 运维实战
  • 域名信息收集(小迪网络安全笔记~
  • 2024.12.15CISCN长城杯铁人三项赛
  • Jinja2模板、Roles角色详解
  • Linux 中的 mkdir 命令:深入解析
  • 10个富士胶片模拟的设置
  • JAVA学习日记(二十六)网络编程
  • MySQL 主从复制与高可用架构
  • 金蝶云苍穹踩过的坑(慢慢更新)
  • Java21 虚拟线程
  • epoll反应堆模型
  • python导出requirements.txt的方法
  • 浅议Flink lib包下的依赖项