GORM(1)-入门指南
GORM(1)-入门指南
一、概述
1.1 特性
- 全功能ORM(几乎)
- 关联(包含一个,包含多个,属于,多对多,多种包含)
- Callbacks(创建/保存/更新/删除/查找之前/之后)
- 预加载(急加载)
- 事务
- 复合主键
- SQL Builder
- 自动迁移
- 日志
- 可扩展,编写基于GORM回调的插件
- 每个功能都有测试
- 开发人员友好
1.2 安装
1go get -u github.com/jinzhu/gorm
1.3 快速入门
1package main
2
3import (
4 "github.com/jinzhu/gorm"
5 _ "github.com/jinzhu/gorm/dialects/sqlite"
6)
7
8type Product struct {
9 gorm.Model
10 Code string
11 Price uint
12}
13
14func main() {
15 db, err := gorm.Open("sqlite3", "test.db")
16 if err != nil {
17 panic("failed to connect database")
18 }
19 defer db.Close()
20
21 // Migrate the schema
22 db.AutoMigrate(&Product{})
23
24 // 创建
25 db.Create(&Product{Code: "L1212", Price: 1000})
26
27 // 读取
28 var product Product
29 db.First(&product, 1) // 查询id为1的product
30 db.First(&product, "code = ?", "L1212") // 查询code为l1212的product
31
32 // 更新 - 更新product的price为2000
33 db.Model(&product).Update("Price", 2000)
34
35 // 删除 - 删除product
36 db.Delete(&product)
37}
二、模型定义
2.1 模型定义
模型(Models)通常只是正常的 golang structs、基本的 go 类型或它们的指针。 同时也支持sql.Scanner
及driver.Valuer
接口(interfaces)。
模型(Model)示例:
1type User struct {
2 gorm.Model
3 Name string
4 Age sql.NullInt64
5 Birthday *time.Time
6 Email string `gorm:"type:varchar(100);unique_index"`
7 Role string `gorm:"size:255"` // 设置字段大小为255
8 MemberNumber *string `gorm:"unique;not null"` // 设置会员号(member number)唯一并且不为空
9 Num int `gorm:"AUTO_INCREMENT"` // 设置 num 为自增类型
10 Address string `gorm:"index:addr"` // 给address字段创建名为addr的索引
11 IgnoreMe int `gorm:"-"` // 忽略本字段
12}
2.2 结构体标记(tags)
标记(tags)在声明模型时是可选项。gorm 支持以下标记:
支持的结构体标记(Struct tags)
结构体标记(Tag) | 描述 |
---|---|
Column | 指定列名 |
Type | 指定列数据类型 |
Size | 指定列大小, 默认值255 |
PRIMARY_KEY | 将列指定为主键 |
UNIQUE | 将列指定为唯一 |
DEFAULT | 指定列默认值 |
PRECISION | 指定列精度 |
NOT NULL | 将列指定为非 NULL |
AUTO_INCREMENT | 指定列是否为自增类型 |
INDEX | 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引 |
UNIQUE_INDEX | 和 INDEX 类似,只不过创建的是唯一索引 |
EMBEDDED | 将结构设置为嵌入 |
EMBEDDED_PREFIX | 设置嵌入结构的前缀 |
- | 忽略此字段 |
关联 struct 的标记(tags)
关联 struct 的详情请查看关联部分
结构体标记(Tag) | 描述 |
---|---|
MANY2MANY | 指定连接表 |
FOREIGNKEY | 设置外键 |
ASSOCIATION_FOREIGNKEY | 设置关联外键 |
POLYMORPHIC | 指定多态类型 |
POLYMORPHIC_VALUE | 指定多态值 |
JOINTABLE_FOREIGNKEY | 指定连接表的外键 |
ASSOCIATION_JOINTABLE_FOREIGNKEY | 指定连接表的关联外键 |
SAVE_ASSOCIATIONS | 是否自动完成 save 的相关操作 |
ASSOCIATION_AUTOUPDATE | 是否自动完成 update 的相关操作 |
ASSOCIATION_AUTOCREATE | 是否自动完成 create 的相关操作 |
ASSOCIATION_SAVE_REFERENCE | 是否自动完成引用的 save 的相关操作 |
PRELOAD | 是否自动完成预加载的相关操作 |
三、约定
3.1 gorm.Model
gorm.Model
是一个包含了ID
, CreatedAt
, UpdatedAt
, DeletedAt
四个字段的GoLang结构体。
你可以将它嵌入到你自己的模型中,当然你也可以完全使用自己的模型。
1// gorm.Model 定义
2type Model struct {
3 ID uint `gorm:"primary_key"`
4 CreatedAt time.Time
5 UpdatedAt time.Time
6 DeletedAt *time.Time
7}
8
9// Inject fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt` into model `User`
10// 将 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`字段注入到`User`模型中
11type User struct {
12 gorm.Model
13 Name string
14}
15
16// 不使用gorm.Model定义模型
17type User struct {
18 ID int
19 Name string
20}
3.2 ID
作为主键
GORM 默认会使用名为ID
的字段作为表的主键。
1type User struct {
2 ID string // 名为`ID`的字段会默认作为表的主键
3 Name string
4}
5
6// 使用`AnimalID`作为主键
7type Animal struct {
8 AnimalID int64 `gorm:"primary_key"`
9 Name string
10 Age int64
11}
3.3 表名(Table Name)
表名默认就是结构体名称的复数,例如:
1type User struct {} // 默认表名是 `users`
2
3// 将 User 的表名设置为 `profiles`
4func (User) TableName() string {
5 return "profiles"
6}
7
8func (u User) TableName() string {
9 if u.Role == "admin" {
10 return "admin_users"
11 } else {
12 return "users"
13 }
14}
15
16// 禁用默认表名的复数形式,如果置为 true,则 `User` 的默认表名是 `user`
17db.SingularTable(true)
指定表名称
1// 使用User结构体创建名为`deleted_users`的表
2db.Table("deleted_users").CreateTable(&User{})
3
4var deleted_users []User
5db.Table("deleted_users").Find(&deleted_users)
6//// SELECT * FROM deleted_users;
7
8db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
9//// DELETE FROM deleted_users WHERE name = 'jinzhu';
更改默认表名称(table name)
你可以通过定义DefaultTableNameHandler
来设置默认表名的命名规则
1gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
2 return "prefix_" + defaultTableName;
3}
3.4 下划线分割命名(Snake Case)的列名
列名由字段名称进行下划线分割来生成
1type User struct {
2 ID uint // column name is `id`
3 Name string // column name is `name`
4 Birthday time.Time // column name is `birthday`
5 CreatedAt time.Time // column name is `created_at`
6}
7
8// Overriding Column Name
9type Animal struct {
10 AnimalId int64 `gorm:"column:beast_id"` // set column name to `beast_id`
11 Birthday time.Time `gorm:"column:day_of_the_beast"` // set column name to `day_of_the_beast`
12 Age int64 `gorm:"column:age_of_the_beast"` // set column name to `age_of_the_beast`
13}
3.5 时间点(Timestamp)跟踪
CreatedAt
如果模型有 CreatedAt
字段,该字段的值将会是初次创建记录的时间。
1db.Create(&user) // `CreatedAt`将会是当前时间
2
3// 可以使用`Update`方法来改变`CreateAt`的值
4db.Model(&user).Update("CreatedAt", time.Now())
UpdatedAt
如果模型有UpdatedAt
字段,该字段的值将会是每次更新记录的时间。
1db.Save(&user) // `UpdatedAt`将会是当前时间
2
3db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`将会是当前时间
DeletedAt
如果模型有DeletedAt
字段,调用Delete
删除该记录时,将会设置DeletedAt
字段为当前时间,而不是直接将记录从数据库中删除。
四、连接数据库
4.1 连接数据库
想要连接数据库,你需要先导入对应数据库的驱动,比如:
1import _ "github.com/go-sql-driver/mysql"
GORM 已经包装了一些驱动,以便更容易的记住导入路径,所以你可以这样导入 mysql 的驱动:
1import _ "github.com/jinzhu/gorm/dialects/mysql"
2// import _ "github.com/jinzhu/gorm/dialects/postgres"
3// import _ "github.com/jinzhu/gorm/dialects/sqlite"
4// import _ "github.com/jinzhu/gorm/dialects/mssql"
4.2 所支持的数据库
MySQL
注意:
想要能正确的处理 time.Time
,你需要添加 parseTime
参数。 (更多支持的参数)
想要完全的支持 UTF-8 编码,你需要修改charset=utf8
为 charset=utf8mb4
。 详情请查看 utf8mb4.
1import (
2 "github.com/jinzhu/gorm"
3 _ "github.com/jinzhu/gorm/dialects/mysql"
4)
5
6func main() {
7 db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
8 defer db.Close()
9}
如果你想指定主机,你需要使用 ()
. 例如:
1user:password@(localhost)/dbname?charset=utf8&parseTime=True&loc=Local
PostgreSQL
1import (
2 "github.com/jinzhu/gorm"
3 _ "github.com/jinzhu/gorm/dialects/postgres"
4)
5
6func main() {
7 db, err := gorm.Open("postgres", "host=myhost port=myport user=gorm dbname=gorm password=mypassword")
8 defer db.Close()
9}
Sqlite3
注意: 你也可以使用 :memory:
替换一个文件路径。 这会告诉 sqlite 使用内存作为一个临时数据。 当你针对 GORM 应用进行测试时,这特别有用,因为你的测试需要一个真正的数据库,并且该数据库位于内存中,性能也很好。
1import (
2 "github.com/jinzhu/gorm"
3 _ "github.com/jinzhu/gorm/dialects/sqlite"
4)
5
6func main() {
7 db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
8 defer db.Close()
9}
SQL Server
Get started with SQL Server, 它可以运行在你的 Mac、Linux 和 Docker
1import (
2 "github.com/jinzhu/gorm"
3 _ "github.com/jinzhu/gorm/dialects/mssql"
4)
5
6func main() {
7 db, err := gorm.Open("mssql", "sqlserver://username:password@localhost:1433?database=dbname")
8 defer db.Close()
9}
4.3 不支持的数据库
GORM 官方支持上述四个数据库,您可以为不受支持的数据库编写dialects。
- 原文作者:黄忠德
- 原文链接:https://huangzhongde.cn/post/Golang/GORM_1/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。