11 KiB
GORM
QuickStart
GORM为golang的orm框架,其使用示例如下:
package main
import (
"gorm.io/gorm"
"gorm.io/driver/sqlite"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Migrate the schema
db.AutoMigrate(&Product{})
// Create
db.Create(&Product{Code: "D42", Price: 100})
// Read
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42
// Update - update product's price to 200
db.Model(&product).Update("Price", 200)
// Update - update multiple fields
db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // non-zero fields
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
// Delete - delete product
db.Delete(&product, 1)
}
Declaring Models
gorm中,Model通过struct来进行定义,struct中的fields可以为如下类型:
- 基础golang类型
- 指针
- type alias
- 自定义类型
- 自定义类型需要实现
database/sql中的Scanner和Valuer接口
- 自定义类型需要实现
如下为一个Model定义的示例:
type User struct {
ID uint // Standard field for the primary key
Name string // A regular string field
Email *string // A pointer to a string, allowing for null values
Age uint8 // An unsigned 8-bit integer
Birthday *time.Time // A pointer to time.Time, can be null
MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
ActivatedAt sql.NullTime // Uses sql.NullTime for nullable time fields
CreatedAt time.Time // Automatically managed by GORM for creation time
UpdatedAt time.Time // Automatically managed by GORM for update time
ignored string // fields that aren't exported are ignored
}
在上述Model中
- 基础类型的字段可以直接访问,例如
uint, uint8, string等 - 指针类型,例如
*time.Time, *string等,代表该字段值可为空 sql/database中的sql.NullString和sql.NullTime类型,也代表该字段可为空CreatedAt字段和UpdatedAt字段是由Gorm管理的字段,当Record被创建或更新时,该字段的值会自动被注入为当前时间Non-exported fields(首字母不是大写)并不会被映射
约定
Primary Key: 对于每个Model,gorm中将name为ID的field看作默认primary keyTable names: 默认情况下,gorm将struct name转换为snake_case,并将snake_case的复数化作为表名。例如,Userstruct对应的表名为users,GormUserName对应的表名为gorm_user_names。Column Names: gorm会自动将field name转化为snake_case,用于表中字段名的映射Timestamp Field: gorm默认使用CreatedAt和UpdatedAt字段来跟踪数据的创建和更新日期。
上述是gorm管理实体时的默认约定,但是除了默认约定外,gorm也支持对实体进行自定义配置。
gorm.Model
gorm提供了一个预先定义的实体gorm.Model,其中包含了常用字段:
// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
在自定义实体时,可以将Model实体作为一个field包含在自定义实体中,那么Model中定义的实体也会自动包含在自定义实体中。
上述预定义字段含义如下:
ID:每行数据的唯一标识符CreatedAt:行创建时间UpdatedAt:行最后更新时间DeletedAt:用于逻辑删除
Advanced
Field Level Permission
对于Exported Fields(以大写开头的Field),在执行CRUD时GORM默认用友所有权限。但是,gorm允许通过tag来修改field level permission,故而可以将field指定为read-only, write-only, create-only, update-only, ignored。
当字段被标记为
ignored时,若使用gorm migrator创建表时,ignored fields不会被创建。
type User struct {
Name string `gorm:"<-:create"` // allow read and create
Name string `gorm:"<-:update"` // allow read and update
Name string `gorm:"<-"` // allow read and write (create and update)
Name string `gorm:"<-:false"` // allow read, disable write permission
Name string `gorm:"->"` // readonly (disable write permission unless it configured)
Name string `gorm:"->;<-:create"` // allow read and create
Name string `gorm:"->:false;<-:create"` // createonly (disabled read from db)
Name string `gorm:"-"` // ignore this field when write and read with struct
Name string `gorm:"-:all"` // ignore this field when write, read and migrate with struct
Name string `gorm:"-:migration"` // ignore this field when migrate with struct
}
CreatedAt / UpdatedAt
gorm默认使用CreatedAt/UpdatedAt来跟踪record创建和更新时间,如果这些字段被定义,将会在创建/更新操作时设置这些字段。
如果想要为Create/Update字段指定不同的名称,可以为自定义字段指定autoCreateTime和autoUpdateTime tag。
如果想要为时间戳指定不同精度,可以按照如下格式进行定义:
type User struct {
CreatedAt time.Time // Set to current time if it is zero on creating
UpdatedAt int // Set to current unix seconds on updating or if it is zero on creating
Updated int64 `gorm:"autoUpdateTime:nano"` // Use unix nano seconds as updating time
Updated int64 `gorm:"autoUpdateTime:milli"`// Use unix milli seconds as updating time
Created int64 `gorm:"autoCreateTime"` // Use unix seconds as creating time
}
struct embedded
在gorm中,如果想要嵌套类,可以使用如下方式:
- 将匿名struct作为field:
type Author struct { Name string Email string } type Blog struct { Author ID int Upvotes int32 } // equals type Blog struct { ID int64 Name string Email string Upvotes int32 } - 将非匿名struct用
gorm:"embedded"进行标记:type Author struct { Name string Email string } type Blog struct { ID int Author Author `gorm:"embedded"` Upvotes int32 } // equals type Blog struct { ID int64 Name string Email string Upvotes int32 } - 除了指定
gorm:"embeded"tag外,还可以为嵌套struct指定prefix:type Blog struct { ID int Author Author `gorm:"embedded;embeddedPrefix:author_"` Upvotes int32 } // equals type Blog struct { ID int64 AuthorName string AuthorEmail string Upvotes int32 }
field tags
当定义model时,tag是可选的,gorm支持tag如下所示。tag是大小写不敏感的,更推荐使用驼峰的写法。
如果需要指定多个tags,可以将多个tags根据;进行分隔,gorm参数值的转义符为\字符。
| Tag Name | Description |
|---|---|
| column | column db name |
| type | column data type, prefer to use compatible general type, e.g: bool, int, uint, float, string, time, bytes, which works for all databases, and can be used with other tags together, like not null, size, autoIncrement… specified database data type like varbinary(8) also supported, when using specified database data type, it needs to be a full database data type, for example: MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT |
| serializer | specifies serializer for how to serialize and deserialize data into db, e.g: serializer:json/gob/unixtime |
| size | specifies column data size/length, e.g: size:256 |
| primaryKey | specifies column as primary key |
| unique | specifies column as unique |
| default | specifies column default value |
| precision | specifies column precision |
| scale | specifies column scale |
| not null | specifies column as NOT NULL |
| autoIncrement | specifies column auto incrementable |
| autoIncrementIncrement | auto increment step, controls the interval between successive column values |
| embedded | embed the field |
| embeddedPrefix | column name prefix for embedded fields |
| autoCreateTime | track current time when creating, for int fields, it will track unix seconds, use value nano/milli to track unix nano/milli seconds, e.g: autoCreateTime:nano |
| autoUpdateTime | track current time when creating/updating, for int fields, it will track unix seconds, use value nano/milli to track unix nano/milli seconds, e.g: autoUpdateTime:milli |
| index | create index with options, use same name for multiple fields creates composite indexes, refer Indexes for details |
| uniqueIndex | same as index, but create uniqued index |
| check | creates check constraint, eg: check:age > 13, refer Constraints |
| <- | set field’s write permission, <-:create create-only field, <-:update update-only field, <-:false no write permission, <- create and update permission |
| -> | set field’s read permission, ->:false no read permission |
| - | ignore this field, - no read/write permission, -:migration no migrate permission, -:all no read/write/migrate permission |
| comment | add comment for field when migration |