目錄
Gorm Model
在使用ORM工具時,通常我們需要在代碼中定義模型(Models)與數據庫中的數據表進行映射,在GORM中模型(Models)通常是正常定義的結構體、基本的go類型或它們的指針。同時也支持sql.Scanner(掃描)及driver.Valuer(驅動)接口(interfaces)
為了方便模型定義,GORM內置了一個gorm.Model結構體。gorm.Model是一個包含了ID, CreatedAt, UpdatedAt, DeletedAt四個字段的Golang結構體。
// gorm.Model 定義
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
可以將它嵌入到自己的模型中:
// 將 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`字段注入到`User`模型中
type User struct {
gorm.Model
Name string
}
也可以完全自己定義模型:
// 不使用gorm.Model,自行定義模型
type User struct {
ID int
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
Name string
}
模型定義示例
//定義模型
type User struct {
gorm.Model //內嵌gorm.Model
Name string //名字
Age sql.NullInt64 //年齡 零值類型
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"` //結構體的tag
Role string `gorm:"size:255"` // 設置字段大小為255
MemberNumber *string `gorm:"unique;not null"` // 設置會員號(member number)唯一並且不為空
Num int `gorm:"AUTO_INCREMENT"` // 設置 num 為自增類型
Address string `gorm:"index:addr"` // 給address字段創建名為addr的索引
IgnoreMe int `gorm:"-"` // 忽略本字段
}
結構體標記(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 | 設置嵌入結構的前綴 |
| - | 忽略此字段 |
關聯相關標記(tags)
| 結構體標記(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 | 是否自動完成預加載的相關操作 |
例子
package main
import (
"database/sql"
"github.com/jinzhu/gorm"
_"github.com/jinzhu/gorm/dialects/mysql"
"time"
)
type User struct {
gorm.Model
Name string
Age sql.NullInt64
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // 設置字段大小為255
MemberNumber *string `gorm:"unique;not null"` // 設置會員號(member number)唯一並且不為空
Num int `gorm:"AUTO_INCREMENT"` // 設置 num 為自增類型
Address string `gorm:"index:addr"` // 給address字段創建名為addr的索引
IgnoreMe int `gorm:"-"` // 忽略本字段
}
func main() {
db, err := gorm.Open("mysql","root:123456@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.AutoMigrate(&User{})
}

主鍵、表名、列名的約定
主鍵(Primary Key)
GORM 默認會使用名為ID的字段作為表的主鍵。

自定義主鍵
// 使用`AnimalID`作為主鍵
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
func main() {
db, err := gorm.Open("mysql","root:123456@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.AutoMigrate(&Animal{})
}

表名(Table name)
表名默認就是結構體名稱的復數
// 使用`AnimalID`作為主鍵
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
//表名 紫色飛豬
func (Animal) TableName()string {
return "zisefeizhu"
}
func main() {
db, err := gorm.Open("mysql","root:123456@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.AutoMigrate(&Animal{}) //重新建了一個表 不會刪除
}

表名判斷
import (
"database/sql"
"github.com/jinzhu/gorm"
_"github.com/jinzhu/gorm/dialects/mysql"
"time"
)
// 使用`AnimalID`作為主鍵
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
//表名 紫色飛豬
//func (Animal) TableName()string {
//return "zisefeizhu"
//}
func (a Animal) TableName() string {
if a.Name == "admin" {
return "admin_animal"
} else {
return "zisefeizhu"
}
}
func main() {
db, err := gorm.Open("mysql","root:123456@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
animal := Animal{
AnimalID:1,
Name: "admin",
Age: 22,
}
db.AutoMigrate(&animal)
}

刪除表名:drop table biaoming;
表名禁用復數
import (
"database/sql"
"github.com/jinzhu/gorm"
_"github.com/jinzhu/gorm/dialects/mysql"
"time"
)
type User struct {
gorm.Model
Name string
Age sql.NullInt64
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // 設置字段大小為255
MemberNumber *string `gorm:"unique;not null"` // 設置會員號(member number)唯一並且不為空
Num int `gorm:"AUTO_INCREMENT"` // 設置 num 為自增類型
Address string `gorm:"index:addr"` // 給address字段創建名為addr的索引
IgnoreMe int `gorm:"-"` // 忽略本字段
}
// 使用`AnimalID`作為主鍵
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
func main() {
db, err := gorm.Open("mysql","root:123456@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.SingularTable(true) // 禁用默認表名的復數形式,如果置為 true,則 `User` 的默認表名是 `user`
db.AutoMigrate(&User{})
db.AutoMigrate(&Animal{})
}

自定義表名
//使用User結構體創建名為zisefeizhu的表
//db.Table("zisefeizhu").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';
GORM還支持更改默認表名稱規則:
建立一個項目,命名加一個統一的前綴
func main() {
//修改默認的表明規則
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
return "zisefeizhu_" + defaultTableName;
}

列名
列名由字段名稱進行下划線分割來生成
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`
}
可以使用結構體tag指定列名:
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`
}
例子
import (
"database/sql"
"github.com/jinzhu/gorm"
_"github.com/jinzhu/gorm/dialects/mysql"
"time"
)
type User struct {
gorm.Model
Name string
Age sql.NullInt64 `gorm:"column:age_of_the_beast"`
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // 設置字段大小為255
MemberNumber *string `gorm:"unique;not null"` // 設置會員號(member number)唯一並且不為空
Num int `gorm:"AUTO_INCREMENT"` // 設置 num 為自增類型
Address string `gorm:"index:addr"` // 給address字段創建名為addr的索引
IgnoreMe int `gorm:"-"` // 忽略本字段
}
func main() {
//修改默認的表明規則
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
return "zisefeizhu_" + defaultTableName;
}
db, err := gorm.Open("mysql","root:123456@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.SingularTable(true) // 禁用默認表名的復數形式,如果置為 true,則 `User` 的默認表名是 `user`
db.AutoMigrate(&User{})
}

時間戳跟蹤
CreatedAt
如果模型有 CreatedAt字段,該字段的值將會是初次創建記錄的時間。
db.Create(&user) // `CreatedAt`將會是當前時間
// 可以使用`Update`方法來改變`CreateAt`的值
db.Model(&user).Update("CreatedAt", time.Now())
UpdatedAt
如果模型有UpdatedAt字段,該字段的值將會是每次更新記錄的時間。
db.Save(&user) // `UpdatedAt`將會是當前時間
db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`將會是當前時間
DeletedAt
如果模型有DeletedAt字段,調用Delete刪除該記錄時,將會設置DeletedAt字段為當前時間,而不是直接將記錄從數據庫中刪除。
