Go語言Gorm框架學習筆記

Go語言Gorm框架學習筆記

Gorm是Go語言的一個orm框架,類似Java中的JPA的實現(Hibernate、EclipseLink等)。

本文目的

本文就是按照官網官方說明,自己動手嘗試下,增加記憶,僅此而已。

安裝

Go語言Gorm框架學習筆記

進入專案目錄安裝gorm

➜ Go-Gorm-Notes git:(main) ✗ go get -u gorm。io/gormgo: added github。com/jinzhu/inflection v1。0。0go: added github。com/jinzhu/now v1。1。5go: added gorm。io/gorm v1。23。10

我用的資料庫是mysql,所以還需要引入Mysql驅動

➜ Go-Gorm-Notes git:(main) ✗ go get -u gorm。io/driver/mysqlgo: added github。com/go-sql-driver/mysql v1。6。0go: added gorm。io/driver/mysql v1。3。6

建立連線

下面程式碼是建立一個Mysql的gorm。DB,之後的操作都要使用這個DB。

package modelsimport ( “gorm。io/driver/mysql” “gorm。io/gorm”)var Db = initDb()//初始化資料庫連線func initDb() *gorm。DB { // Mysql的連結字串,我電腦上使用者名稱是root,密碼是qwe!@#123 dsn := “root:qwe!@#123@tcp(127。0。0。1:3306)/go-gorm?charset=utf8mb4&parseTime=True&loc=Local” // Mysql驅動有自己的配置選項,可以透過 mysql。New(mysql。Config{})配置。具體可看mysql。Config。 Db, _ := gorm。Open(mysql。Open(dsn), &gorm。Config{}) return Db}

Model

對於這種ORM框架,Model是特別重要的,也是值得去深入學習的地方,因為一個小問題,可能就會引發資料庫的問題。

初識

我會建立一個簡單的Model,並使用gorm的自動建立資料庫表功能,來看看如何做到透過Model自動建立表。

建立一個Author結構體

package modelsimport “gorm。io/gorm”type Author struct { gorm。Model Name string}

main方法中使用來自動建立資料庫表

package mainimport “Go-Gorm-Notes/models”func main() { // 使用AutoMigrate自動建立資料庫表 models。Db。AutoMigrate(&models。Author{})}

執行後會發現數據庫中多了一個叫做authors的表。請注意這個名字,這是gorm自動建立的,能否自己指定呢?肯定是可以的,看下自動建立的表的結構如下:

create table authors( id bigint unsigned auto_increment primary key, created_at datetime(3) null, updated_at datetime(3) null, deleted_at datetime(3) null, name longtext null);create index idx_authors_deleted_at on authors (deleted_at);

說明:id,created_at,updated_at,deleted_at都是因為Author結構體繼承了gorm。Model。這是gorm自身提供的,我們也可以不使用它,如果不用就要自己定義主鍵欄位。

另外name欄位是自己加的,但是name欄位的型別是longtext,這可能不是我們想要的,我們可能想要的是name是varchar(200)這樣的型別,也是可以自定義的。官網都有說明,接下來我一一嘗試下,並記錄下來。

自定義表名

自定義表名需要實現gorm。schema下的TableName方法。

package modelsimport “gorm。io/gorm”type Author struct { gorm。Model Name string}// TableName 自定義表名func (Author) TableName() string { return “author”}

重新執行看看是否會自動建立author表

Go語言Gorm框架學習筆記

模型定義

欄位標籤

可以在結構體欄位名後面使用gorm:xxx的機構來配置標籤,從而達到自定義資料庫列資訊的效果。

宣告 model 時,tag 是可選的,GORM 支援以下 tag: tag 名大小寫不敏感,但建議使用 camelCase 風格

標籤名

說明

column

指定 db 列名

type

列資料型別,推薦使用相容性好的通用型別,例如:所有資料庫都支援 bool、int、uint、float、string、time、bytes 並且可以和其他標籤一起使用,例如:not null、size, autoIncrement… 像 varbinary(8) 這樣指定資料庫資料型別也是支援的。在使用指定資料庫資料型別時,它需要是完整的資料庫資料型別,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT

serializer

指定將資料序列化或反序列化到資料庫中的序列化器, 例如: serializer:json/gob/unixtime

size

定義列資料型別的大小或長度,例如 size: 256

primaryKey

將列定義為主鍵

unique

將列定義為唯一鍵

default

定義列的預設值

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

column

定義列的名字,比如如下程式碼將Name欄位對應的資料庫列名為t_name。

Name string `gorm:“column:t_name”`

type

列資料型別,推薦使用相容性好的通用型別,例如:所有資料庫都支援 bool、int、uint、float、string、time、bytes 並且可以和其他標籤一起使用,例如:not null、size, autoIncrement… 像 varbinary(8) 這樣指定資料庫資料型別也是支援的。在使用指定資料庫資料型別時,它需要是完整的資料庫資料型別,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT

比如我繼續設定Name欄位為varchar(200) not null default ‘’

Name string `gorm:“column:name;type:varchar(200) not null default ‘’”`

Go語言Gorm框架學習筆記

可以看到型別等資訊已經正確設定。

size

定義列資料型別的大小或長度,例如 size: 256

Sex string `gorm:“size:10”`

這裡我沒有使用name欄位,是因為Name欄位制定了type,型別varchar(200),再指定size無效。

primarykey

上面的結構體我使用了gorm。Model,gorm自動給我生成了主鍵,現在我要自己定義主鍵,重新定義下結構體

package modelstype Author struct { ID uint `gorm:“primarykey”` Name string `gorm:“column:name;type:varchar(200) not null default ‘’;”` Sex string `gorm:“size:10”`}// TableName 自定義表名func (Author) TableName() string { return “author”}

我使用

ID uint `gorm:“primarykey”`

定義ID是主鍵。

Go語言Gorm框架學習筆記

unique

使用unique就會設定唯一索引。

Name string `gorm:“column:name;type:varchar(200) not null default ‘’;unique”`

結果如下:

Go語言Gorm框架學習筆記

default

設定預設值

Sex string `gorm:“size:10;default:‘男’”`

Go語言Gorm框架學習筆記

index

Name string `gorm:“column:name;type:varchar(200) not null default ‘’;index”`

Go語言Gorm框架學習筆記

建立了一個普通索引。

uniqueIndex

建立唯一索引

// 身份資訊唯一Identify string `gorm:“size:100;uniqueIndex”`

需要注意的是上面的size:100;不能去掉,使用它可以是資料庫型別變為varchar,否則型別是longtext,這個類似不能加唯一索引的。會報錯。

Go語言Gorm框架學習筆記

not null

指定列不能為空

Identify string `gorm:“size:100;uniqueIndex;not null;”`

Go語言Gorm框架學習筆記

autoCreateTime

建立記錄時自動填充時間,取值nano或者milli。

Go語言Gorm框架學習筆記

插入一條記錄

models。Db。Save(&models。Author{Name: “張飛”, Identify: “001”})

結果是:

id

name

sex

identify

ct_time_nano

ct_time_milli

ct_nano

ct_milli

1

張飛

001

2022-10-07 12:11:47。854

2022-10-07 12:11:47。854

1665115907854000000

1665115907854

autoUpdateTime

跟autoCreateTime類似。

embedded

內嵌欄位,將一個結構體嵌入進來

package modelsimport “time”type Author struct { ID uint `gorm:“primarykey”` Name string `gorm:“column:name;type:varchar(200) not null default ‘’;index”` Sex string `gorm:“size:10;default:‘男’”` // 身份資訊唯一 Identify string `gorm:“size:100;uniqueIndex;not null;”` CtTimeNano time。Time `gorm:“autoCreateTime:nano”` //nano/milli CtTimeMilli time。Time `gorm:“autoCreateTime:milli”` CtNano int `gorm:“autoCreateTime:nano”` CtMilli int `gorm:“autoCreateTime:milli”` ConcatWay `gorm:“embedded”`}// ConcatWay 聯絡方式type ConcatWay struct { Address string Phone string Email string}// TableName 自定義表名func (Author) TableName() string { return “author”}

執行AutoMigrate後,資料庫表結構如下

Go語言Gorm框架學習筆記

增加了Address結構體下的欄位。

embeddedPrefix

對於內嵌的結構體欄位,增加字首,預設是空

ConcatWay `gorm:“embedded;embeddedPrefix:cw_”`

Go語言Gorm框架學習筆記

comment

欄位的備註資訊

ID uint `gorm:“primarykey;comment:主鍵ID”`

Go語言Gorm框架學習筆記

serializer

指定將資料序列化或反序列化到資料庫中的序列化器, 例如: serializer:json/gob/unixtime

ByteJson []byte `gorm:“serializer:json”`ConcatWayJSON ConcatWay `gorm:“serializer:json”`ConcatWayGob ConcatWay `gorm:“serializer:gob”`TimeUnixtime int64 `gorm:“serializer:unixtime;type:time”` //將int64的內容轉化為ddatetime儲存

Go語言Gorm框架學習筆記

儲存一條資料

models。Db。Create(&models。Author{ Name: “張飛”, Identify: “001”, ByteJson: []byte(“位元組切片”), ConcatWayJSON: models。ConcatWay{Address: “https://itlab1024。com”, Email: “itlab1024@163。com”}, ConcatWayGob: models。ConcatWay{Address: “https://itlab1024。com”, Email: “itlab1024@163。com”}, TimeUnixtime: 12,})

id

name

sex

identify

ct_time_nano

ct_time_milli

ct_nano

ct_milli

cw_address

cw_phone

cw_email

byte_json

concat_way_json

concat_way_gob

time_unixtime

1

張飛

001

2022-10-07 14:27:01。859

2022-10-07 14:27:01。859

1665124021859000000

1665124021859

“5a2X6IqC5YiH54mH”

{“Address”:“https://itlab1024。com”,“Phone”:“”,“Email”:“itlab1024@163。com”}

0x37FF8103010109436F6E63617457617901FF82000103010741646472657373010C00010550686F6E65010C000105456D61696C010C0000002DFF82011568747470733A2F2F69746C6162313032342E636F6D021169746C616231303234403136332E636F6D00

1970-01-01 08:00:12

autoIncrement

設定列自增,需要與type標籤聯合使用

autoIncrementIncrement

設定列自增步長,需要與type標籤聯合使用

unique

設定唯一鍵

check

設定約束,比如設定name的值不能等於abc

Name string `gorm:“check:name <> ‘abc’”`

關聯

Belongs To

belongs to 會與另一個模型建立了一對一的連線。 這種模型的每一個例項都“屬於”另一個模型的一個例項。就是誰屬於誰,比如一個人屬於一個國家。

看如下如下兩個結構體User和Country

package modelsimport “gorm。io/gorm”type User struct { gorm。Model Name string CountryId uint // 這裡不能使用匿名 Country Country}type Country struct { *gorm。Model Name string}

自動建立表後,可以得到如下結構

Go語言Gorm框架學習筆記

使用者表的country_id和country表的id關聯了起來。一對一的關係。

Has One

has one 與另一個模型建立一對一的關聯,但它和一對一關係有些許不同。 這種關聯表明一個模型的每個例項都包含或擁有另一個模型的一個例項。

例如,您的應用包含 user 和 credit card 模型,且每個 user 只能有一張 credit card。

// User 有一張 CreditCard,UserID 是外來鍵type User struct { gorm。Model CreditCard CreditCard}type CreditCard struct { gorm。Model Number string UserID uint}

Go語言Gorm框架學習筆記

可以看到users表沒有credit的相關欄位。

再看下credit_cards表

Go語言Gorm框架學習筆記

該表的userId關聯到了user表的ID欄位。

Has Many

類似於has one,只不過這裡要使用的是切片

// User 有多張 CreditCard,UserID 是外來鍵type User struct { gorm。Model CreditCards []CreditCard}type CreditCard struct { gorm。Model Number string UserID uint}

創建出來的表如下:

users表:

Go語言Gorm框架學習筆記

credit_cards表如下:

Go語言Gorm框架學習筆記

跟has one建立的表結構是一樣的。

Many To Many

Many to Many 會在兩個 model 中新增一張連線表,可以透過標籤many2manay設定關聯表的名字。

// User 擁有並屬於多種 language,`user_languages` 是連線表type User struct { gorm。Model Languages []Language `gorm:“many2many:user_languages;”`}type Language struct { gorm。Model Name string}

會建立user_languages中間表,並且關聯表中的user_id跟User表的ID關聯,language_id跟languages表的id關聯。

Go語言Gorm框架學習筆記

上面的都是使用預設的情況,比如外來鍵名稱等,如果想更換名字等資訊,就得重寫外來鍵,這裡我就一一說明了。

原生SQL

待更新。。。