diff --git a/Golang/gorm.md b/Golang/gorm.md index 2a1c588..27bede3 100644 --- a/Golang/gorm.md +++ b/Golang/gorm.md @@ -1,6 +1,13 @@ - [GORM](#gorm) - [QuickStart](#quickstart) - [Declaring Models](#declaring-models) + - [约定](#约定) + - [gorm.Model](#gormmodel) + - [Advanced](#advanced) + - [Field Level Permission](#field-level-permission) + - [CreatedAt / UpdatedAt](#createdat--updatedat) + - [struct embedded](#struct-embedded) + - [field tags](#field-tags) # GORM @@ -74,6 +81,233 @@ type User struct { - 基础类型的字段可以直接访问,例如`uint, uint8, string`等 - 指针类型,例如`*time.Time, *string`等,代表该字段值可为空 - `sql/database`中的`sql.NullString`和`sql.NullTime`类型,也代表该字段可为空 -- `CreateAt`字段和`UpdatedAt`字段是由Gorm管理的字段,当Record被创建或更新时,该字段的值会自动被注入为当前时间 +- `CreatedAt`字段和`UpdatedAt`字段是由Gorm管理的字段,当Record被创建或更新时,该字段的值会自动被注入为当前时间 - `Non-exported fields`(首字母不是大写)并不会被映射 +### 约定 +- `Primary Key`: 对于每个Model,gorm中将name为`ID`的field看作默认primary key +- `Table names`: 默认情况下,gorm将struct name转换为`snake_case`,并将`snake_case`的`复数化`作为表名。例如,`User`struct对应的表名为`users`,`GormUserName`对应的表名为`gorm_user_names`。 +- `Column Names`: gorm会自动将field name转化为`snake_case`,用于表中字段名的映射 +- `Timestamp Field`: gorm默认使用`CreatedAt`和`UpdatedAt`字段来跟踪数据的创建和更新日期。 + +上述是gorm管理实体时的默认约定,但是除了默认约定外,gorm也支持对实体进行自定义配置。 + +### gorm.Model +gorm提供了一个预先定义的实体`gorm.Model`,其中包含了常用字段: +```go +// 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不会被创建`。 + + +```go +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。 + +如果想要为时间戳指定不同精度,可以按照如下格式进行定义: +```go +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: + ```golang + 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"`进行标记: + ```golang + 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: + ```golang + 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 | +