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 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。