gorm是一個使用Go語言編寫的ORM框架。它文檔齊全,對開發者友好,支持主流數據庫。
gorm介紹
中文官方網站內含十分齊全的中文文檔,有了它你甚至不需要再繼續向下閱讀本文。
安裝
go get -u github.com/jinzhu/gorm
連接數據庫
連接不同的數據庫都需要導入對應數據的驅動程序,GORM
已經貼心的為我們包裝了一些驅動程序,只需要按如下方式導入需要的數據庫驅動即可:
import _ "github.com/jinzhu/gorm/dialects/mysql" // import _ "github.com/jinzhu/gorm/dialects/postgres" // import _ "github.com/jinzhu/gorm/dialects/sqlite" // import _ "github.com/jinzhu/gorm/dialects/mssql"
連接MySQL
import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) func main() { db, err := gorm.Open("mysql", "user:password@(localhost)/dbname?charset=utf8mb4&parseTime=True&loc=Local") defer db.Close() }
連接PostgreSQL
基本代碼同上,注意引入對應postgres
驅動並正確指定gorm.Open()
參數。
import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/postgres" ) func main() { db, err := gorm.Open("postgres", "host=myhost port=myport user=gorm dbname=gorm password=mypassword") defer db.Close() }
連接Sqlite3
基本代碼同上,注意引入對應sqlite
驅動並正確指定gorm.Open()
參數。
import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" ) func main() { db, err := gorm.Open("sqlite3", "/tmp/gorm.db") defer db.Close() }
連接SQL Server
基本代碼同上,注意引入對應mssql
驅動並正確指定gorm.Open()
參數。
import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mssql" ) func main() { db, err := gorm.Open("mssql", "sqlserver://username:password@localhost:1433?database=dbname") defer db.Close() }
GORM基本示例
注意:
- 本文以MySQL數據庫為例,講解GORM各項功能的主要使用方法。
- 往下閱讀本文前,你需要有一個能夠成功連接上的MySQL數據庫實例。
Docker快速創建MySQL實例
很多同學如果不會安裝MySQL或者懶得安裝MySQL,可以使用一下命令快速運行一個MySQL8.0.19實例,當然前提是你要有docker環境…
在本地的13306
端口運行一個名為mysql8019
,root用戶名密碼為root1234
的MySQL容器環境:
docker run --name mysql8019 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=root1234 -d mysql:8.0.19
在另外啟動一個MySQL Client
連接上面的MySQL環境,密碼為上一步指定的密碼root1234
:
docker run -it --network host --rm mysql mysql -h127.0.0.1 -P13306 --default-character-set=utf8mb4 -uroot -p
創建數據庫
在使用GORM前手動創建數據庫db1
:
CREATE DATABASE db1;
GORM操作MySQL
使用GORM連接上面的db1
進行創建、查詢、更新、刪除操作。
package main import ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) // UserInfo 用戶信息 type UserInfo struct { ID uint Name string Gender string Hobby string } func main() { db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local") if err!= nil{ panic(err) } defer db.Close() // 自動遷移 db.AutoMigrate(&UserInfo{}) u1 := UserInfo{1, "七米", "男", "籃球"} u2 := UserInfo{2, "沙河娜扎", "女", "足球"} // 創建記錄 db.Create(&u1) db.Create(&u2) // 查詢 var u = new(UserInfo) db.First(u) fmt.Printf("%#v\n", u) var uu UserInfo db.Find(&uu, "hobby=?", "足球") fmt.Printf("%#v\n", uu) // 更新 db.Model(&u).Update("hobby", "雙色球") // 刪除 db.Delete(&u) }
GORM Model定義
在使用ORM工具時,通常我們需要在代碼中定義模型(Models)與數據庫中的數據表進行映射,在GORM中模型(Models)通常是正常定義的結構體、基本的go類型或它們的指針。 同時也支持sql.Scanner
及driver.Valuer
接口(interfaces)。
gorm.Model
為了方便模型定義,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 Name string }
模型定義示例
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:"-"` // 忽略本字段 }
結構體標記(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 | 是否自動完成預加載的相關操作 |
主鍵、表名、列名的約定
主鍵(Primary Key)
GORM 默認會使用名為ID的字段作為表的主鍵。
type User struct { ID string // 名為`ID`的字段會默認作為表的主鍵 Name string } // 使用`AnimalID`作為主鍵 type Animal struct { AnimalID int64 `gorm:"primary_key"` Name string Age int64 }
表名(Table Name)
表名默認就是結構體名稱的復數,例如:
type User struct {} // 默認表名是 `users` // 將 User 的表名設置為 `profiles` func (User) TableName() string { return "profiles" } func (u User) TableName() string { if u.Role == "admin" { return "admin_users" } else { return "users" } } // 禁用默認表名的復數形式,如果置為 true,則 `User` 的默認表名是 `user` db.SingularTable(true)
也可以通過Table()
指定表名:
// 使用User結構體創建名為`deleted_users`的表 db.Table("deleted_users").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還支持更改默認表名稱規則:
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string { return "prefix_" + defaultTableName; }
列名(Column Name)
列名由字段名稱進行下划線分割來生成
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` }
時間戳跟蹤
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
字段為當前時間,而不是直接將記錄從數據庫中刪除。