对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现OOP编程语言里不同类型系统的数据之间的转换,通常是指"对象-关系映射"(Object/Relational Mapping)
面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
ORM简要介绍
ORM相当于中继数据
简单的说,ORM相当于中继数据,实现了数据库中底层数据到软件应用层的数据映射
1
2
3
| 数据库的表(table) --> 类(class)
记录(record,行数据)--> 对象(object)
字段(field)--> 对象的属性(attribute)
|
ORM优缺点
优点:
- ORM充当MVC架构中的Model层,架构也更清晰明了,让数据模块在同一个地方,易于维护
- ORM相关的工具包库提供了相关的数据标准化操作,比如SQL转义、事务、SQL预处理等
- 操作数据过程,调用起来更类似对象的操作,对研发来说,屏蔽了底层的SQL细节,避免了一些性能不佳的SQL
缺点:
- 针对复杂SQL,ORM性能存在一定的短板,ORM更偏向于解决简单关系(一对一、一对多、多对多)
- 对数据层的抽象,开发者无法了解底层的数据库操作,也无法定制一些特殊的SQL。
- 学习成本开销
Golang - GORM
主要特性
Gorm 是基于Golang语言在github开源上星最多的一个ORM库,其相关特性:
- ORM的的基本功能
- 关联支持(一对一、一对多、多对多)
- SQL钩子(在创建/保存/更新/删除/查找之前或之后执行事件)
- SQL预加载(提速SQL性能)
- 事务支持
- SQL 生成器
- 数据库自动迁移
- 自定义日志
GORM - Code实践
创建gorm-learn环境
初始化自己项目环境(基于Module),项目目录:/data/go/proj/github.com/tkstorm/gorm-learn
gorm.Model介绍
gorm.Model是一个基本的GoLang结构,它包含以下字段:ID,CreatedAt,UpdatedAt,DeletedAt。
1
2
3
4
5
6
7
| // gorm.Model definition
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
|
模型
模型定义
1
2
3
4
5
6
7
8
9
10
11
| // Inject fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt` into model `User`
type User struct {
gorm.Model
Name string
}
// Declaring model w/o gorm.Model
type User struct {
ID int
Name string
}
|
模型中列定义标记
结构化标记用于在创建数据库或者插入数据记录时候,做出相应的SQL操作说明(比如主键、索引、字段声明、备注等等)
标签(grom:"xx-tag:xx-val" ) | 标签说明 |
---|
Column | 指定列名 |
Type | 指定列数据类型 |
Size | 指定列大小, 默认值255 |
PRIMARY_KEY | 将列指定为主键 |
UNIQUE | 将列指定为唯一 |
DEFAULT | 指定列默认值 |
PRECISION | 指定列精度 |
NOT NULL | 将列指定为非 NULL |
AUTO_INCREMENT | 指定列是否为自增类型 |
INDEX | 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引 |
UNIQUE_INDEX | 创建唯一索引 |
EMBEDDED | 将结构设置为嵌入 |
EMBEDDED_PREFIX | 设置嵌入结构的前缀 |
- | 忽略此字段 |
模型中列的关联关系标记
参考:https://gorm.io/zh_CN/docs/models.html
主键
1
2
3
4
5
6
7
8
9
10
11
| type User struct {
ID int // field named `ID` will be used as primary field by default
Name string
}
// Set field `AnimalID` as primary field
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
|
表名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| type User struct {} // default table name is `users`
// Set User's table name to be `profiles`
func (User) TableName() string {
return "profiles"
}
func (u User) TableName() string {
if u.Role == "admin" {
return "admin_users"
} else {
return "users"
}
}
// Disable table name's pluralization, if set to true, `User`'s table name will be `user`
db.SingularTable(true)
|
统一添加表名前缀 - DefaultTableNameHandler
1
2
3
| gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
return "prefix_" + defaultTableName;
}
|
指定表名称操作(db.Table)
1
2
3
4
5
6
7
| // Create `deleted_users` table with struct User's definition
db.Table("deleted_users").CreateTable(&User{})
var deleted_users []User
db.Table("deleted_users").Find(&deleted_users)
//// SELECT * FROM deleted_users;
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
//// DELETE FROM deleted_users WHERE name = 'jinzhu';
|
列名
列名称将是该字段的名称是较低的蛇形列表
1
2
3
4
5
6
7
8
9
10
11
12
13
| type User struct {
ID uint // column name is `id`
Name string // column name is `name`
Birthday time.Time // column name is `birthday`
CreatedAt time.Time // column name is `created_at`
}
// Overriding Column Name
type Animal struct {
AnimalId int64 `gorm:"column:beast_id"` // set column name to `beast_id`
Birthday time.Time `gorm:"column:day_of_the_beast"` // set column name to `day_of_the_beast`
Age int64 `gorm:"column:age_of_the_beast"` // set column name to `age_of_the_beast`
}
|
列元素
CreatedAt:行记录创建时间
1
2
3
| db.Create(&user) // will set `CreatedAt` to current time
// To change its value, you could use `Update`
db.Model(&user).Update("CreatedAt", time.Now())
|
UpdatedAt:行记录更新时间
1
2
| db.Save(&user) // will set `UpdatedAt` to current time
db.Model(&user).Update("name", "jinzhu") // will set `UpdatedAt` to current time
|
DeletedAt:行记录删除时间
1
2
3
4
5
6
7
8
9
10
| db.Delete(&user)
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
// Batch Delete
db.Where("age = ?", 20).Delete(&User{})
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
// Delete record permanently with Unscoped
db.Unscoped().Delete(&order)
// DELETE FROM orders WHERE id=10;
|
参考
- 阮一峰ORM教程:http://www.ruanyifeng.com/blog/2019/02/orm-tutorial.html
- Wiki ORM: https://zh.wikipedia.org/zh-cn/对象关系映射
- GORM 文档: https://gorm.io/zh_CN/docs/connecting_to_the_database.html