MyGorm - Go从零实现ORM
MyGorm是从零实现Go的ORM框架,对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。

序言

对象和数据库是如何映射

数据库 对象表
表(table) 类(struct)
记录(record, row) 对象 (object)
字段(field, column) 对象属性(attribute)

现在看起来比较抽象,举个例子就形象很多了。
比如在Mysql数据库中:

1
2
3
CREATE TABLE `Student` (`Name` text, `Scope` integer);
INSERT INTO `Student` (`Name`, `Scope`) VALUES ("张三", 98);
SELECT * FROM `Student`;

如果我们使用了ORM框架,在Go中的写法如下:

Student.go
1
2
3
4
5
6
7
8
9
type Student struct {
Name string
Scope int
}

mygorm.CreateTable(&Student{})
mygorm.Save(&Student{"张三", 98})
var students []Student
mygorm.Find(&students)

ORM 相当于是对象与数据库的映射关系,可以把数据库中的一条条数据想象成一个个对象,一张表的数据,相当于相同对象的集合,我们通过操作对象集合的方法,从而实现对关系型数据库的操作。

如何实现一个 ORM 框架

根据上面的例子,看到对数据库操作,传递了对象从而实现对关系型数据库的操作。但是ORM 框架是怎么知道上面的 “张三”对应的是数据库中的Name的,这个时候就不得不提到反射了,Go 语言的反射机制(reflect),通过反射,可以获取到对象对应的结构体名称,成员变量、方法等信息。

例如在下面的例子中:

main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
"reflect"
)

type Student struct {
Name string
Scope int
}

func main() {

valueOf := reflect.ValueOf(&Student{"张三", 98}).Elem()

for i := 0; i < valueOf.NumField(); i++ {
fieldValue := valueOf.Field(i)
fieldType := valueOf.Field(i).Type()
fmt.Println(fieldValue, fieldType)
}

}

上面的测试代码,会把字段和字段类型输出。

1
2
3
~ go run student.go
张三 string
98 int
  • reflect.ValueOf() 获取指针对应的反射值。
  • (reflect.Type).Field(i).Type() 获取第 i 个成员变量类型。
  • (reflect.Type).Field(i) 获取第 i 个成员变量。

关于MyGorm

MyGorm主要基于MySQL开发

  • 简单的增删查改使用 ORM 替代 SQL 语句是很简单的,但是实际应用中不仅仅是对单表进行CURD,比如复杂的多表关联查询,ORM 也需要支持,因此,设计实现一个 ORM 框架,先从简单的入手。万丈高楼平地起,一砖一瓦皆根基。就像Mygin一样。

  • Go 语言中使用比较广泛 ORM 框架是 gormxorm。除了基础的功能,比如表的操作,记录的增删查改,gorm 还实现了关联关系(一对一、一对多等),回调插件等;xorm 实现了读写分离(支持配置多个数据库),数据同步,导入导出等。

MyGorm目的主要是了解 ORM 框架设计的原理,具体实现的功能有:

  • 表的创建、删除、迁移。
  • 记录的增删查改,查询条件的链式操作。
  • 单一主键的设置(primary key)。
  • 钩子(在创建/更新/删除/查找之前或之后)
  • 事务(transaction)。



本站由 [PengBin](/) 使用 [Stellar 1.26.3](https://github.com/xaoxuu/hexo-theme-stellar/tree/1.26.3) 主题创建。 本博客所有文章除特别声明外,均采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 许可协议,转载请注明出处。