内容简介:源代码/数据集已上传到对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。
源代码/数据集已上传到 Github – 7days-golang
1 谈谈 ORM 框架
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。
那对象和数据库是如何映射的呢?
数据库 | 面向对象的编程语言 |
---|---|
表(table) | 类(class/struct) |
记录(record, row) | 对象 (object) |
字段(field, column) | 对象属性(attribute) |
举一个具体的例子,来理解 ORM。
CREATE TABLE `User` (`Name` text, `Age` integer); INSERT INTO `User` (`Name`, `Age`) VALUES ("Tom", 18); SELECT * FROM `User`;
第一条 SQL 语句,在数据库中创建了表User,并且定义了 2 个字段Name和Age;第二条 SQL 语句往表中添加了一条记录;最后一条语句返回表中的所有记录。
假如我们使用了 ORM 框架,可以这么写:
type User struct { Name string Age int } orm.CreateTable(&User{}) orm.Save(&User{"Tom", 18}) var users []User orm.Find(&users)
ORM 框架相当于对象和数据库中间的一个桥梁,借助 ORM 可以避免写繁琐的 SQL 语言,仅仅通过操作具体的对象,就能够完成对关系型数据库的操作。
那如何实现一个 ORM 框架呢?
- CreateTable方法需要从参数&User{}得到对应的结构体的名称 User 作为表名,成员变量 Name, Age 作为列名,同时还需要知道成员变量对应的类型。
- Save方法则需要知道每个成员变量的值。
- Find方法仅从传入的空切片&[]User,得到对应的结构体名也就是表名 User,并从数据库中取到所有的记录,将其转换成 User 对象,添加到切片中。
如果这些方法只接受 User 类型的参数,那是很容易实现的。但是 ORM 框架是通用的,也就是说可以将任意合法的对象转换成数据库中的表和记录。例如:
type Account struct { Username string Password string } orm.CreateTable(&Account{})
这就面临了一个很重要的问题:如何根据任意类型的指针,得到其对应的结构体的信息。这涉及到了 Go 语言的反射机制(reflect),通过反射,可以获取到对象对应的结构体名称,成员变量、方法等信息,例如:
typ := reflect.Indirect(reflect.ValueOf(&Account{})).Type() fmt.Println(typ.Name()) // Account for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) fmt.Println(field.Name) // Username Password }
- reflect.ValueOf()获取指针对应的反射值。
- reflect.Indirect()获取指针指向的对象的反射值。
- (reflect.Type).Name()返回类名(字符串)。
- (reflect.Type).Field(i)获取第 i 个成员变量。
除了对象和表结构/记录的映射以外,设计 ORM 框架还需要关注什么问题呢?
1)MySQL,PostgreSQL,SQLite 等数据库的 SQL 语句是有区别的,ORM 框架如何在开发者不感知的情况下适配多种数据库?
2)如何对象的字段发生改变,数据库表结构能够自动更新,即是否支持数据库自动迁移(migrate)?
3)数据库支持的功能很多,例如事务(transaction),ORM 框架能实现哪些?
4)…
2 关于 GeeORM
数据库的特性非常多,简单的增删查改使用 ORM 替代 SQL 语句是没有问题的,但是也有很多特性难以用 ORM 替代,比如复杂的多表关联查询,ORM 也可能支持,但是基于性能的考虑,开发者自己写 SQL 语句很可能更高效。
因此,设计实现一个 ORM 框架,就需要给功能特性排优先级了。
Go 语言中使用比较广泛 ORM 框架是 gorm 和 xorm 。除了基础的功能,比如表的操作,记录的增删查改,gorm 还实现了关联关系(一对一、一对多等),回调插件等;xorm 实现了读写分离(支持配置多个数据库),数据同步,导入导出等。
gorm 正在彻底重构 v1 版本,短期内看不到发布 v2 的可能。相比于 gorm-v1,xorm 在设计上更清晰。GeeORM
的设计主要参考了 xorm,一些细节上的实现参考了 gorm。GeeORM 的目的主要是了解 ORM
框架设计的原理,具体实现上鲁棒性做得不够,一些复杂的特性,例如 gorm 的关联关系,xorm 的读写分离没有实现。目前支持的特性有:
- 表的创建、删除、迁移。
- 记录的增删查改,查询条件的链式操作。
- 单一主键的设置(primary key)。
- 钩子(在创建/更新/删除/查找之前或之后)
- 事务(transaction)。
GeeORM分7天实现,每天完成的部分都是可以独立运行和测试的,就像搭积木一样,一个个独立的特性组合在一起就是最终的 ORM 框架。每天的代码在 100 行左右,同时配有较为完备的单元测试用例。
- 第一天: database/sql 基础 | Code
- 第二天: 对象表结构映射 | Code
- 第三天: 记录新增和查询 | Code
- 第四天: 链式操作与更新删除 | Code
- 第五天: 实现钩子(Hooks) | Code
- 第六天: 支持事务(Transaction) | Code
- 第七天: 数据库迁移(Migrate) | Code
附 推荐阅读
以上所述就是小编给大家介绍的《7 天用 Go 从零实现 ORM 框架 GeeORM》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 自己实现集合框架(十):顺序栈的实现
- Golang实现简单爬虫框架(4)——队列实现并发任务调度
- 简易RPC框架实现
- 优秀开源框架的扩展机制实现
- Go 实现简易 RPC 框架
- 如何实现一个Python爬虫框架
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
使用HTML5和Node构建超媒体API
【美】Mike Amundsen(麦克.阿蒙森) / 臧秀涛 / 电子工业出版社 / 2014-5 / 55.00元
《使用HTML5和Node构建超媒体API》探讨了超媒体API 的设计,介绍了作为超媒体API 的构件块的超媒体因子,并讲解了基本格式、状态转移、领域风格和应用流程这4 种超媒体设计元素;之后作者结合具体的场景,通过3个动手实验章节,从超媒体因子和超媒体设计元素入手,用实际的代码向我们详细地演示了超媒体API 的设计;最后介绍了超媒体设计的文档编写、注册与发布等内容。 《使用HTML5和No......一起来看看 《使用HTML5和Node构建超媒体API》 这本书的介绍吧!