Gorm
ä»Âä¹Âæ¯ORM
Object Relational Mappingï¼Â对象堳系æ å°Â
ç»ÂæÂÂä½ å SQLæ°æ®åºÂÃ¥ÂÂå¨æ å°Âï¼Âè¿Â个æ¶åÂÂå°±æÂÂäºÂORMè¯ÂÃ¥ÂÂ¥
ä¸Âå¥è¯Â说ï¼Âå°±æ¯å°Âæ°æ®åºÂä¸ÂçÂÂ表æ°æ®åÂÂç»ÂæÂÂä½Âè¿Âè¡Â对åºÂçÂÂ堳系
ORMçÂÂä¼Â缺ç¹
ä¼Âç¹ï¼Â
- æÂÂé«Âå¼ÂÃ¥ÂÂæÂÂçÂÂ
缺ç¹:
- çºç²æ§è¡Âæ§è½ãÂÂä¸Âé´å¤ÂäºÂä¸Â个ç¯èÂÂãÂÂ
- çºç²çµ活æ§
- å¼±åÂÂSQLè½åÂÂ
gormä»Âç»Â
ä¸ÂæÂÂå®Âæ¹ç½Âç«Âå å«åÂÂÃ¥ÂÂé½Âå ¨çÂÂä¸ÂæÂÂæÂÂæ¡£ï¼ÂæÂÂäºÂå®Âä½ çÂÂè³ä¸ÂéÂÂè¦ÂÃ¥ÂÂ继ç»ÂÃ¥ÂÂä¸Âé 读æ¾ÂÂãÂÂ
gormæ¯ä¸Â个使ç¨Goè¯Âè¨Âç¼ÂÃ¥ÂÂçÂÂORMæ¡Âæ¶ãÂÂå®ÂæÂÂæ¡£é½Âå ¨ï¼Â对å¼ÂÃ¥ÂÂè åÂÂ好ï¼Âæ¯æÂÂ主æµÂæ°æ®åºÂãÂÂ
å®Âè£Â
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
注æÂÂï¼Â
- GORM çÂÂå¼ÂÃ¥ÂÂå·²ç»Âè¿Â移è³ github.com/go-gormï¼Âimport è·¯å¾Âä¹Âä¿®æ¹为
gorm.io/gorm
ï¼Â对äºÂ以åÂÂçÂÂ项ç®ï¼Âæ¨å¯以继ç»Â使ç¨github.com/jinzhu/gorm
- æ°æ®åºÂ驱å¨被æÂÂÃ¥ÂÂ为ç¬ç«ÂçÂÂ项ç®ï¼Âä¾Âå¦Âï¼Âgithub.com/go-gorm/mysâ¦ï¼Âä¸Âå®Âç import è·¯å¾Âä¹ÂÃ¥ÂÂæ´为
gorm.io/driver/mysql
è¿ÂæÂÂ¥MySQL
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
}
注æÂÂï¼Âæ³è¦Âæ£确çÂÂå¤ÂçÂÂ
time.Time
ï¼Âæ¨éÂÂè¦Â带ä¸ÂparseTime
Ã¥ÂÂæ°@(æ´å¤ÂÃ¥ÂÂæ°) è¦Âæ¯æÂÂå®Âæ´ç UTF-8 ç¼Âç Âï¼Âæ¨éÂÂè¦Âå°Âcharset=utf8
æ´æ¹为charset=utf8mb4
æÂ¥ç æ¤æÂÂç« è·åÂÂ详æ ãÂÂ
GORMåºæ¬示ä¾Â
Ã¥ÂÂ建æ°æ®åºÂ
å¨使ç¨GORMÃ¥ÂÂæÂÂå¨åÂÂ建æ°æ®åºÂgorm
ï¼Âæ¨èÂÂ使ç¨å¾形åÂÂæ°æ®åºÂ管çÂÂ软件ï¼Âä¾Âå¦ÂNavicat
CREATE DATABASE gorm;
GORMæÂÂä½ÂMySQL
使ç¨GORMè¿ÂæÂ¥ä¸Âé¢çÂÂgorm
è¿Âè¡ÂÃ¥ÂÂ建ãÂÂæ¥询ãÂÂæ´æ°ãÂÂå é¤æÂÂä½ÂãÂÂ
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// UserInfo ç¨æ·信æ¯
type UserInfo struct {
ID uint
Name string
Gender string
Hobby string
}
func main() {
dsn := "root:@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// èªå¨è¿Â移
err = db.AutoMigrate(&UserInfo{})
if err != nil {
panic("failed to migrate")
}
u1 := UserInfo{1, "æ¨æ´Â", "ç·", "篮çÂÂ"}
// Ã¥ÂÂ建记å½Â
db.Create(&u1)
db.Create(&UserInfo{2, "çÂÂæ¥Âç¶", "女", "足çÂÂ"})
// æ¥询
var u = new(UserInfo)
db.First(&u, 1) // æ ¹æ®æ´åÂÂ主é®æÂ¥æ¾
fmt.Printf("%#v\n", u)
var uu UserInfo
db.First(&uu, "hobby=?", "足çÂÂ") //æÂ¥æ¾ hobby Ã¥ÂÂ段å¼为 足ç çÂÂè®°å½Â
fmt.Printf("%#v\n", uu)
// æ´æ°
db.Model(&u).Update("hobby", "æÂÂçÂÂ")
//Update - æ´æ°å¤Â个åÂÂ段
db.Model(&u).Updates(UserInfo{Name: "èÂÂæÂÂ", Hobby: "è·³èÂÂ"}) // ä»Â
æ´æ°éÂÂé¶å¼åÂÂ段
db.Model(&uu).Updates(map[string]interface{}{"Hobby": "æ¼ÂæÂÂ", "Name": "赵丽é¢Â"})
// å é¤
db.Delete(&u, 1)
}
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
}
ä¹Âå¯以éÂÂè¿Âæ Âç¾ embedded
å°ÂÃ¥Â
¶åµÂÃ¥Â
¥ï¼Âä¾Âå¦Âï¼Â
type Author struct {
Name string
Email string
}
type Blog struct {
ID int
Author Author `gorm:"embedded"`
Upvotes int32
}
// çÂÂæÂÂäºÂ
type Blog struct {
ID int64
Name string
Email string
Upvotes int32
}
è¿Âå¯以使ç¨æ Âç¾ embeddedPrefix
æ¥为 db ä¸ÂçÂÂÃ¥ÂÂ段åÂÂæ·»å åÂÂç¼Âï¼Âä¾Âå¦Âï¼Â
type Blog struct {
ID int
Author Author `gorm:"embedded;embeddedPrefix:author_"`
Upvotes int32
}
// çÂÂæÂÂäºÂ
type Blog struct {
ID int64
AuthorName string
AuthorEmail string
Upvotes int32
}
å½Âç¶你ä¹Âå¯以å®Âå ¨èª己å®Âä¹Â模åÂÂï¼Â
// ä¸Â使ç¨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:"-"` // 忽çÂ¥æÂŒÂÂ段
}
GORM å¾åÂÂäºÂ约å®Âä¼ÂäºÂéÂ
Âç½® é»Â认æÂÂ
åµä¸Âï¼ÂGORM 使ç¨ ID
ä½Â为主é®ï¼Â使ç¨ç»ÂæÂÂä½ÂÃ¥ÂÂç èÂÂå½¢å¤Âæ°
ä½Â为表åÂÂï¼ÂÃ¥ÂÂ段åÂÂç èÂÂå½¢
ä½Â为åÂÂÃ¥ÂÂï¼Â并使ç¨ CreatedAt
ãÂÂUpdatedAt
Ã¥ÂÂ段追踪åÂÂ建ãÂÂæ´æ°æ¶é´ãÂÂ
å¦ÂæÂÂæ¨éµ循 GORM çÂÂ约å®Âï¼Âæ¨就å¯以å°ÂÃ¥ÂÂçÂÂé Âç½®ãÂÂ代ç Âã å¦ÂæÂÂ约å®Âä¸Â符åÂÂæ¨çÂÂå®Âé è¦Âæ±Âï¼ÂGORM å Â许你é Âç½®å®Â们
ç»ÂæÂÂä½Âæ Âè®°ï¼Âtagsï¼Â
声æ model æ¶ï¼Âtag æ¯å¯éÂÂçÂÂï¼ÂGORM æ¯æÂÂ以丠tagï¼ tag Ã¥ÂÂ大å°ÂÃ¥ÂÂä¸ÂæÂÂæÂÂï¼Âä½Â建议使ç¨ camelCase
é£Âæ ¼
æ¯æÂÂçÂÂç»ÂæÂÂä½Âæ Âè®°ï¼ÂStruct tagsï¼Â
æ Âç¾å | 说æ |
---|---|
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 | æÂÂå®ÂÃ¥ÂÂçÂÂ精度 |
scale | æÂÂå®ÂÃ¥ÂÂ大尠|
not null | æÂÂå®ÂÃ¥ÂÂ为 NOT NULL |
autoIncrement | æÂÂå®ÂÃ¥ÂÂ为èªå¨å¢Âé¿ |
autoIncrementIncrement | èªå¨æÂ¥é¿ï¼Âæ§å¶è¿Âç»Âè®°å½Âä¹Âé´çÂÂé´é |
embedded | åµÂå¥ÂÃ¥ÂÂ段 |
embeddedPrefix | åµÂå ¥åÂÂ段çÂÂÃ¥ÂÂÃ¥ÂÂÃ¥ÂÂç¼ |
å ³èÂÂç¸堳æ Âè®°ï¼Âtagsï¼Â
æ Âç¾ | æÂÂè¿° |
---|---|
foreignKey | æÂÂå®Âå½ÂÃ¥ÂÂ模åÂÂçÂÂÃ¥ÂÂä½Â为è¿Âæ¥表çÂÂå¤Âé® |
references | æÂÂå®Âå¼Âç¨表çÂÂÃ¥ÂÂÃ¥ÂÂï¼Âå ¶å°Â被æ å°Â为è¿Âæ¥表å¤Âé® |
polymorphic | æÂÂå®Âå¤ÂæÂÂç±»åÂÂï¼Âæ¯Âå¦Â模åÂÂå |
polymorphicValue | æÂÂå®Âå¤ÂæÂÂå¼ãÂÂé»Â认表å |
many2many | æÂÂå®Âè¿Âæ¥表表å |
joinForeignKey | æÂÂå®Âè¿Âæ¥表çÂÂå¤Âé®åÂÂÃ¥ÂÂï¼Âå ¶å°Â被æ å°Âå°å½ÂÃ¥ÂÂ表 |
joinReferences | æÂÂå®Âè¿Âæ¥表çÂÂå¤Âé®åÂÂÃ¥ÂÂï¼Âå ¶å°Â被æ å°Âå°å¼Âç¨表 |
constraint | Ã¥Â
³ç³»çº¦æÂÂï¼Âä¾Âå¦Âï¼ÂOnUpdate ãÂÂOnDelete |
主é®ãÂÂ表åÂÂãÂÂÃ¥ÂÂÃ¥ÂÂçÂÂ约å®Â
主é®ï¼Â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ï¼Â
GORM 使ç¨ç»ÂæÂÂä½ÂÃ¥ÂÂç èÂÂå½¢å½åÂÂ
ä½Â为表åÂÂãÂÂ对äºÂç»ÂæÂÂä½ User
ï¼Âæ ¹æ®约å®Âï¼ÂÃ¥Â
¶è¡¨åÂÂ为 users
type User struct {} // é»Â认表åÂÂæ¯ `users`
type Tabler interface {
TableName() string
}
// TableName ä¼Âå° User çÂÂ表åÂÂéÂÂÃ¥ÂÂ为 `profiles`
func (User) TableName() string {
return "profiles"
}
注æÂÂï¼Â
TableName
ä¸Âæ¯æÂÂå¨æÂÂÃ¥ÂÂÃ¥ÂÂï¼Âå®Âä¼Â被ç¼ÂÃ¥ÂÂä¸Âæ¥以便åÂÂç»Â使ç¨ãÂÂæ³è¦Â使ç¨å¨æÂÂ表åÂÂï¼Âä½ å¯以使ç¨Scopes
ï¼Âä¾Âå¦Âï¼Â
func UserTable(user User) func (tx *gorm.DB) *gorm.DB {
return func (tx *gorm.DB) *gorm.DB {
if user.Admin {
return tx.Table("admin_users")
}
return tx.Table("users")
}
}
db.Scopes(UserTable(user)).Create(&user)
è¿Âå¯以ç¦Âç¨é»Â认表åÂÂçÂÂå¤Âæ°形å¼Âï¼Âå¦ÂæÂÂ置为 trueï¼Âå User
çÂÂé»Â认表åÂÂæ¯ user
ï¼Â该æ¹æ³ÂéÂÂç¨äºÂv1çÂÂï¼Âä¹Âå°±æ¯import "github.com/jinzhu/gorm"
db.SingularTable(true)
ä¹Âå¯以éÂÂè¿ÂTable()
æÂÂå®Â表åÂÂï¼Â
// æ ¹æ® User çÂÂÃ¥ÂÂ段åÂÂ建 `deleted_users` 表
db.Table("deleted_users").AutoMigrate(&User{})
// ä»Âå¦ä¸Â张表æ¥询æ°æ®
var deletedUsers []User
db.Table("deleted_users").Find(&deletedUsers)
// SELECT * FROM deleted_users;
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
// 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`å°Âä¼Âæ¯å½ÂÃ¥ÂÂæ¶é´
user2 := User{Name: "jinzhu", CreatedAt: time.Now()}
db.Create(&user2) // user2 ç `CreatedAt` ä¸Âä¼Â被修æ¹
// å¯以使ç¨`Update`æ¹æ³ÂæÂ¥æ¹åÂÂ`CreateAt`çÂÂå¼
db.Model(&user).Update("CreatedAt", time.Now())
ä½ å¯以éÂÂè¿Âå° autoCreateTime
æ Âç¾置为 false
æÂ¥ç¦Âç¨æ¶é´æ³追踪ï¼Âä¾Âå¦Âï¼Â
type User struct {
CreatedAt time.Time `gorm:"autoCreateTime:false"`
}
UpdatedAt
å¦ÂæÂÂ模åÂÂæÂÂUpdatedAt
Ã¥ÂÂ段ï¼Â该åÂÂ段çÂÂå¼å°Âä¼Âæ¯æ¯Â次æ´æ°记å½ÂçÂÂæ¶é´ãÂÂ
db.Save(&user) // `UpdatedAt`å°Âä¼Âæ¯å½ÂÃ¥ÂÂæ¶é´
db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`å°Âä¼Âæ¯å½ÂÃ¥ÂÂæ¶é´
db.Model(&user).UpdateColumn("name", "jinzhu") // `UpdatedAt` ä¸Âä¼Â被修æ¹
user2 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Create(&user2) // Ã¥ÂÂ建记å½Âæ¶ï¼Âuser2 ç `UpdatedAt` ä¸Âä¼Â被修æ¹
user3 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Save(&user3) // æ´æ°æ¶ï¼Âuser3 ç `UpdatedAt` ä¼Âä¿®æ¹为å½ÂÃ¥ÂÂæ¶é´
ä½ å¯以éÂÂè¿Âå° autoUpdateTime
æ Âç¾置为 false
æÂ¥ç¦Âç¨æ¶é´æ³追踪ï¼Âä¾Âå¦Âï¼Â
type User struct {
UpdatedAt time.Time `gorm:"autoUpdateTime:false"`
}
DeletedAt
å¦ÂæÂÂ模åÂÂæÂÂDeletedAt
Ã¥ÂÂ段ï¼Âè°Âç¨Delete
å é¤该记å½Âæ¶ï¼Âå°Âä¼Â设置DeletedAt
Ã¥ÂÂ段为å½ÂÃ¥ÂÂæ¶é´ï¼ÂèÂÂä¸Âæ¯ç´æÂ¥å°Âè®°å½Âä»Âæ°æ®åºÂä¸Âå é¤ãÂÂ
Ã¥ÂÂ建
Ã¥ÂÂ建记å½Â
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"time"
)
type User struct {
ID uint
Name string
Age uint8
Birthday time.Time
}
func main() {
dsn := "root:@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// èªå¨è¿Â移
err = db.AutoMigrate(&User{})
if err != nil {
panic("failed to migrate")
}
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // éÂÂè¿Âæ°æ®çÂÂæÂÂéÂÂæÂ¥åÂÂ建
fmt.Println(user.ID) // è¿ÂÃ¥ÂÂæÂÂÃ¥Â
¥æ°æ®çÂÂ主é®
fmt.Println(result.Error) // è¿Âå error
fmt.Println(result.RowsAffected) // è¿ÂÃ¥ÂÂæÂÂÃ¥Â
¥è®°å½ÂçÂÂæ¡æ°
}
æÂÂ们è¿Âå¯以使ç¨ Create()
Ã¥ÂÂ建å¤Â项记å½Âï¼Â
users := []User{
{Name: "Jinzhu", Age: 18, Birthday: time.Now()},
{Name: "Jackson", Age: 19, Birthday: time.Now()},
}
result := db.Create(users) // pass a slice to insert multiple row
fmt.Println(result.Error) // returns error
fmt.Println(result.RowsAffected) // returns inserted records count
ç¨æÂÂå®ÂçÂÂÃ¥ÂÂ段åÂÂ建记å½Â
Ã¥ÂÂ建记å½Â并为æÂÂå®ÂçÂÂÃ¥ÂÂ段åÂÂé Âå¼ï¼Â
db.Select("Name", "Age", "CreatedAt").Create(&user)
// INSERT INTO `users` (`name`,`age`,`created_at`) VALUES ("jinzhu", 18, "2020-07-04 11:05:21.775")
Ã¥ÂÂ建记å½Â并忽çÂ¥è¦ÂçÂÂçÂ¥çÂÂä¼ éÂÂÃ¥ÂÂ段çÂÂå¼ï¼Â
db.Omit("Name", "Age", "CreatedAt").Create(&user)
// INSERT INTO `users` (`birthday`,`updated_at`) VALUES ("2020-01-01 00:00:00.000", "2020-07-04 11:05:21.775")
æ¹éÂÂæÂÂå ¥
èÂ¥è¦ÂæÂÂæÂÂå°æÂÂÃ¥Â
¥å¤§éÂÂè®°å½Âï¼Â请å°Âä¸Â个åÂÂçÂÂä¼ éÂÂç» Create
æ¹æ³ÂãÂÂGORM å°ÂçÂÂæÂÂä¸Â个åÂÂ獠SQL è¯Âå¥æÂ¥æÂÂÃ¥Â
¥æÂÂæÂÂæ°æ®并åÂÂ填主é®å¼ï¼Âé©åÂÂæ¹æ³Âä¹Âå°Â被è°Âç¨ãÂÂå½Âè®°å½Âå¯以åÂÂæÂÂå¤Â个æ¹å¤ÂçÂÂæ¶ï¼Âå®Âå°Âå¼Âå§Âä¸Â个äºÂå¡ãÂÂ
var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.Create(&users)
for _, user := range users {
fmt.Println(user.ID) // 1,2,3
}
å¯以å¨使ç¨ CreateInBatches
Ã¥ÂÂ建æ¶æÂÂå®Âæ¹å¤ÂçÂÂ大å°Âï¼Âä¾Âå¦Âï¼Â
var users = []User{{Name: "jinzhu_1"}, ...,{Name: "jinzhu_10000"}}
// batch size 100
db.CreateInBatches(users, 100)
æ ¹æ® Map Ã¥ÂÂ建
GORM æ¯æÂÂä» map [ string ] interface {}
Ã¥ÂÂ[] map [ string ] interface {}{}
Ã¥ÂÂ建ï¼Âä¾Âå¦Âï¼Â
db.Model(&User{}).Create(map[string]interface{}{
"Name": "jinzhu", "Age": 18,
})
// batch insert from `[]map[string]interface{}{}`
db.Model(&User{}).Create([]map[string]interface{}{
{"Name": "jinzhu_1", "Age": 18},
{"Name": "jinzhu_2", "Age": 20},
})
注æÂÂ: ä» map Ã¥ÂÂ建æ¶ï¼Âä¸Âä¼Âè°Âç¨ hookï¼Âä¸Âä¼Âä¿ÂÃ¥ÂÂå ³èÂÂï¼Â主é®å¼ä¹Âä¸Âä¼Âè¿ÂÃ¥ÂÂå¡«å Â
é»Â认å¼
å¯以éÂÂè¿ tag å®Âä¹ÂÃ¥ÂÂ段çÂÂé»Â认å¼ï¼Âæ¯Âå¦Âï¼Â
type User struct {
ID int64
Name string `gorm:"default:galeone"`
Age int64
}
注æÂÂï¼ÂéÂÂè¿Âtagå®Âä¹ÂÃ¥ÂÂ段çÂÂé»Â认å¼ï¼Âå¨åÂÂ建记å½Âæ¶åÂÂçÂÂæÂÂç SQL è¯Âå¥ä¼ÂæÂÂé¤没æÂÂå¼æÂÂå¼为 é¶å¼ çÂÂÃ¥ÂÂ段ã å¨å°Âè®°å½ÂæÂÂå ¥å°æ°æ®åºÂÃ¥ÂÂï¼ÂGormä¼Âä»Âæ°æ®åºÂå 载é£äºÂÃ¥ÂÂ段çÂÂé»Â认å¼ãÂÂ
举个ä¾ÂÃ¥ÂÂï¼Â
var user = User{Name: "", Age: 99}
db.Create(&user)
ä¸Âé¢代ç Âå®ÂéÂÂ
æ§è¡ÂçÂÂSQLè¯Âå¥æ¯INSERT INTO users("age") values('99');
ï¼ÂæÂÂé¤äºÂé¶å¼åÂÂ段Name
ï¼ÂèÂÂå¨æ°æ®åºÂä¸Âè¿Âä¸Âæ¡æ°æ®ä¼Â使ç¨设置çÂÂé»Â认å¼ä½Â为NameÃ¥ÂÂ段çÂÂå¼ãÂÂ
**注æÂÂï¼Â**æÂÂæÂÂÃ¥ÂÂ段çÂÂé¶å¼, æ¯Âå¦Â0
, ""
,false
æÂÂèÂÂ
Ã¥Â
¶å®Âé¶å¼
ï¼Âé½ä¸Âä¼Âä¿ÂÃ¥ÂÂå°æ°æ®åºÂÃ¥ÂÂ
ï¼Âä½Âä¼Â使ç¨ä»Â们çÂÂé»Â认å¼ã å¦ÂæÂÂä½ æ³é¿åÂ
Âè¿Âç§ÂæÂÂ
Ã¥Â括Âå¯以èÂÂèÂÂ使ç¨æÂÂéÂÂæÂÂå®Âç° Scanner/Valuer
æÂ¥å£ï¼Âæ¯Âå¦Âï¼Â
使ç¨æÂÂéÂÂæ¹å¼Âå®Âç°é¶å¼åÂÂå ¥æ°æ®åºÂ
// 使ç¨æÂÂéÂÂ
type User struct {
ID int64
Name *string `gorm:"default:galeone"`
Age int64
}
user := User{Name: new(string), Age: 18}
db.Create(&user) // æ¤æ¶æ°æ®åºÂä¸Â该æ¡记å½ÂnameÃ¥ÂÂ段çÂÂå¼就æ¯''
使ç¨Scanner/ValueræÂ¥å£æ¹å¼Âå®Âç°é¶å¼åÂÂå ¥æ°æ®åºÂ
// 使ç¨ Scanner/Valuer
type User struct {
ID int64
Name sql.NullString `gorm:"default:'galeone'"` // sql.NullString å®Âç°äºÂScanner/ValueræÂ¥å£
Age int64
}
user := User{Name: sql.NullString{Valid: true}, Age: 18}
db.Create(&user) // æ¤æ¶æ°æ®åºÂä¸Â该æ¡记å½ÂnameÃ¥ÂÂ段çÂÂå¼就æ¯''
æ©å±ÂÃ¥ÂÂ建éÂÂ项
ä¾Âå¦ÂPostgreSQL
æ°æ®åºÂä¸Âå¯以使ç¨ä¸Âé¢çÂÂæ¹å¼Âå®Âç°åÂÂ并æÂÂÃ¥Â
Â¥, æÂÂÃ¥ÂÂæ´æ°, æ åÂÂæÂÂÃ¥Â
¥ãÂÂ
// 为Instertè¯Âå¥添å æ©å±ÂSQLéÂÂ项
db.Set("gorm:insert_option", "ON CONFLICT").Create(&product)
// INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT;
æ¥询
ä¸Âè¾¥询
GORM æÂÂä¾Â亠First
ãÂÂTake
ãÂÂLast
æ¹æ³Âï¼Â以便ä»Âæ°æ®åºÂä¸Âæ£Âç´¢åÂÂ个对象ãÂÂå½Âæ¥询æ°æ®åºÂæ¶å®Âæ·»å 亠LIMIT 1
æ¡件ï¼Âä¸Â没æÂÂæ¾å°记å½Âæ¶ï¼Âå®Âä¼Âè¿Âå ErrRecordNotFound
éÂÂ误ãÂÂ
// æ ¹æ®主é®æ¥询第ä¸Âæ¡记å½Â
var user User
result := db.First(&user)
fmt.Println(result.RowsAffected) // è¿ÂÃ¥ÂÂæ¾å°çÂÂè®°å½Âæ°
fmt.Println(result.Error) // returns error or nil
//// SELECT * FROM users ORDER BY id LIMIT 1;
// éÂÂæºè·åÂÂä¸Âæ¡记å½Â
db.Take(&user)
//// SELECT * FROM users LIMIT 1;
// æ ¹æ®主é®æ¥询æÂÂÃ¥ÂÂä¸Âæ¡记å½Â
db.Last(&user)
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
// æ¥询æÂÂæÂÂçÂÂè®°å½Â
db.Find(&users)
//// SELECT * FROM users;
// æ¥询æÂÂå®ÂçÂÂæÂÂæ¡记å½Â(ä»Â
å½Â主é®为æ´åÂÂæ¶å¯ç¨)
db.First(&user, 10)
//// SELECT * FROM users WHERE id = 10;
db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;
db.First(&user, "10")
// SELECT * FROM users WHERE id = 10;
db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);
//主é®为åÂÂ符串
db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a"
å¦ÂæÂÂä½ æ³é¿å Â
ErrRecordNotFound
éÂÂ误ï¼Âä½ å¯以使ç¨Find
ï¼Âæ¯Âå¦Âdb.Limit(1).Find(&user)
ï¼ÂFind
æ¹æ³Âå¯以æÂ¥åÂÂstructÃ¥ÂÂsliceçÂÂæ°æ®ãÂÂ
对åÂÂ个对象使ç¨
Find
èÂÂä¸Â带limitï¼Âdb.Find(&user)
å°Âä¼Âæ¥询æ´个表并ä¸Âåªè¿ÂÃ¥ÂÂ第ä¸Â个对象ï¼Âè¿Âæ¯æ§è½ä¸Âé«Â并ä¸Âä¸Âç¡®å®ÂçÂÂãÂÂ
Where æ¡件
æ®éÂÂSQLæ¥询
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;
// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu';
// <>
db.Where("name <> ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
//// SELECT * FROM users WHERE name in ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
//// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
//// SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
//// SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
Struct & Mapæ¥询
// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
// 主é®çÂÂÃ¥ÂÂçÂÂ
db.Where([]int64{20, 21, 22}).Find(&users)
//// SELECT * FROM users WHERE id IN (20, 21, 22);
**æÂÂ示ï¼Â**å½ÂéÂÂè¿Âç»ÂæÂÂä½Âè¿Âè¡Âæ¥询æ¶ï¼ÂGORMå°Âä¼ÂåªéÂÂè¿ÂéÂÂé¶å¼åÂÂ段æ¥询ï¼Âè¿ÂæÂÂå³çÂÂå¦ÂæÂÂä½ çÂÂÃ¥ÂÂ段å¼为0
ï¼Â''
ï¼Âfalse
æÂÂèÂÂ
Ã¥Â
¶ä»Âé¶å¼
æ¶ï¼Âå°Âä¸Âä¼Â被ç¨äºÂæÂÂ建æ¥询æ¡件ï¼Âä¾Âå¦Âï¼Â
db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
//// SELECT * FROM users WHERE name = "jinzhu";
èÂ¥è¦Âå¨æ¥询æ¡件ä¸Âå å«é¶å¼ï¼Âå¯以使ç¨æ å°Âï¼Â该æ å°Âå°Âå å«æÂÂæÂÂé®å¼ä½Â为æ¥询æ¡件ï¼Âä¾Âå¦Â:
db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
æÂÂå®Âç»ÂæÂÂä½Âæ¥询åÂÂ段
å¨使ç¨ struct è¿Âè¡ÂæÂÂç´¢æ¶ï¼Âå¯以éÂÂè¿Âä¼ éÂÂç¸堳çÂÂÃ¥ÂÂ段åÂÂæ dbname å° Where ()æÂ¥æÂÂå®Âå¨æ¥询æ¡件ä¸Â使ç¨ struct ä¸ÂçÂÂåªäºÂç¹å®Âå¼ï¼Âä¾Âå¦Â:
db.Where(&User{Name: "jinzhu"}, "name", "Age").Find(&users)// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
db.Where(&User{Name: "jinzhu"}, "Age").Find(&users)// SELECT * FROM users WHERE age = 0;
Not æ¡件
ä½Âç¨丠Where 类似çÂÂæ 形å¦Âä¸Âï¼Â
db.Not("name", "jinzhu").First(&user)
//// SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;
// Not In
db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
//// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");
// Not In slice of primary keys
db.Not([]int64{1,2,3}).First(&user)
//// SELECT * FROM users WHERE id NOT IN (1,2,3);
db.Not([]int64{}).First(&user)
//// SELECT * FROM users;
// Plain SQL
db.Not("name = ?", "jinzhu").First(&user)
//// SELECT * FROM users WHERE NOT(name = "jinzhu");
// Struct
db.Not(User{Name: "jinzhu"}).First(&user)
//// SELECT * FROM users WHERE name <> "jinzhu";
Oræ¡件
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
// Struct
db.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2", Age: 18}).Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' OR (name = 'jinzhu 2' AND age = 18);
// Map
db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2", "age": 18}).Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' OR (name = 'jinzhu 2' AND age = 18);
å èÂÂæ¡件
ä½Âç¨ä¸ÂWhere
æ¥询类似ï¼Âå½ÂÃ¥ÂÂ
èÂÂæ¡件ä¸Âå¤Â个ç«Âå³æ§è¡Âæ¹æ³Âä¸Â起使ç¨æ¶, Ã¥ÂÂ
èÂÂæ¡件ä¸Âä¼Âä¼ éÂÂç»ÂÃ¥ÂÂé¢çÂÂç«Âå³æ§è¡Âæ¹æ³ÂãÂÂ
// æ ¹æ®主é®è·åÂÂè®°å½ (åªéÂÂç¨äºÂæ´形主é®)
db.First(&user, 23)
//// SELECT * FROM users WHERE id = 23 LIMIT 1;
// æ ¹æ®主é®è·åÂÂè®°å½Â, å¦ÂæÂÂå®Âæ¯ä¸Â个éÂÂæ´形主é®
db.First(&user, "id = ?", "string_primary_key")
//// SELECT * FROM users WHERE id = 'string_primary_key' LIMIT 1;
// Plain SQL
db.Find(&user, "name = ?", "jinzhu")
//// SELECT * FROM users WHERE name = "jinzhu";
db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)
//// SELECT * FROM users WHERE name <> "jinzhu" AND age > 20;
// Struct
db.Find(&users, User{Age: 20})
//// SELECT * FROM users WHERE age = 20;
// Map
db.Find(&users, map[string]interface{}{"age": 20})
//// SELECT * FROM users WHERE age = 20;
补堠ï¼Â
<>
æ¯ SQL ä¸ÂçÂÂæ¯Âè¾Âè¿Âç®Â符ï¼Âç¨äºÂæ£Âæ¥两个å¼æ¯å¦ä¸Âç¸çÂÂãÂÂå¨ Go è¯Âè¨Âä¸Âï¼Â<>
被ç¨ä½Âdb.Find
æ¹æ³ÂçÂÂæ¥询æ¡件ãÂÂ
é¢Âå¤Âæ¥询éÂÂ项
// 为æ¥询 SQL æ·»å é¢Âå¤Âç SQL æÂÂä½Â
db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10)
//// SELECT * FROM users WHERE id = 10 FOR UPDATE;
Find è³ map
GORM Ã¥Â
Â许æ«æÂÂç»ÂæÂÂè³ map[string]interface{}
æ []map[string]interface{}
ï¼Âæ¤æ¶å«å¿ÂäºÂæÂÂå® Model
æ Table
ï¼Âä¾Âå¦Âï¼Â
result := map[string]interface{}{}
db.Model(&User{}).First(&result, "id = ?", 1)
var results []map[string]interface{}
db.Table("users").Find(&results)
FirstOrInit
è·åÂÂ第ä¸Âæ¡å¹é ÂçÂÂè®°å½Âï¼ÂæÂÂè 根æ®ç»Âå®ÂçÂÂæ¡件åÂÂå§ÂÃ¥ÂÂä¸Â个å®Âä¾Âï¼Âä» æ¯æ sturct å map æ¡件ï¼Â
// æªæ¾å° userï¼ÂÃ¥ÂÂæ ¹æ®ç»Âå®ÂçÂÂæ¡件åÂÂå§ÂÃ¥ÂÂä¸Âæ¡记å½Â
db.FirstOrInit(&user, User{Name: "non_existing"})
// user -> User{Name: "non_existing"}
// æ¾å°亠`name` = `jinzhu` ç user
db.Where(User{Name: "jinzhu"}).FirstOrInit(&user)
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}
// æ¾å°亠`name` = `jinzhu` ç user
db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}
å¦ÂæÂÂ没æÂÂæ¾å°记å½Âï¼Âå¯以使ç¨åÂÂ
å«æ´å¤ÂçÂÂå±Âæ§çÂÂç»ÂæÂÂä½ÂÃ¥ÂÂå§Âå userï¼ÂAttrs
ä¸Âä¼Â被ç¨äºÂçÂÂæÂÂæ¥询 SQL
// æªæ¾å° userï¼ÂÃ¥ÂÂæ ¹æ®ç»Âå®ÂçÂÂæ¡件以å Attrs Ã¥ÂÂå§Âå user
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// user -> User{Name: "non_existing", Age: 20}
// æªæ¾å° userï¼ÂÃ¥ÂÂæ ¹æ®ç»Âå®ÂçÂÂæ¡件以å Attrs Ã¥ÂÂå§Âå user
db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// user -> User{Name: "non_existing", Age: 20}
// æ¾å°亠`name` = `jinzhu` ç userï¼ÂÃ¥ÂÂ忽çÂÂ¥ Attrs
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}
ä¸Â管æ¯å¦æ¾å°记å½Âï¼ÂAssign
é½ä¼Âå°Âå±Âæ§èµÂå¼绠structï¼Âä½Âè¿ÂäºÂå±Âæ§ä¸Âä¼Â被ç¨äºÂçÂÂæÂÂæ¥询 SQLï¼Âä¹Âä¸Âä¼Â被ä¿ÂÃ¥ÂÂå°æ°æ®åºÂ
// æªæ¾å° userï¼Âæ ¹æ®æ¡件å Assign å±Âæ§åÂÂå§Âå struct
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
// user -> User{Name: "non_existing", Age: 20}
// æ¾å° `name` = `jinzhu` çÂÂè®°å½Âï¼Âä¾Âç¶ä¼Âæ´æ° Assign ç¸åÂ
³çÂÂå±Âæ§
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user)
// SELECT * FROM USERS WHERE name = jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "Jinzhu", Age: 20}
FirstOrCreate
è·åÂÂå¹éÂ
ÂçÂÂ第ä¸Âæ¡记å½ÂæÂÂèÂÂ
æ ¹æ®ç»Âå®Âæ¡件åÂÂ建ä¸Âæ¡æ°纪å½Âï¼Âä»Â
struct, map æ¡件æÂÂæÂÂï¼Âï¼ÂRowsAffected
è¿ÂÃ¥ÂÂÃ¥ÂÂ建ãÂÂæ´æ°çÂÂè®°å½Âæ°
// æªæ¾å° Userï¼Âæ ¹æ®ç»Âå®Âæ¡件åÂÂ建ä¸Âæ¡æ°纪å½Â
result := db.FirstOrCreate(&user, User{Name: "non_existing"})
// INSERT INTO "users" (name) VALUES ("non_existing");
// user -> User{ID: 112, Name: "non_existing"}
// result.RowsAffected // => 1
// æ¾å° `name` = `jinzhu` ç User
result := db.Where(User{Name: "jinzhu"}).FirstOrCreate(&user)
// user -> User{ID: 111, Name: "jinzhu", "Age": 18}
// result.RowsAffected // => 0
å¦ÂæÂÂ没æÂÂæ¾å°记å½Âï¼Âå¯以使ç¨åÂÂ
å«æ´å¤ÂçÂÂå±Âæ§çÂÂç»ÂæÂÂä½ÂÃ¥ÂÂ建记å½Âï¼ÂAttrs
ä¸Âä¼Â被ç¨äºÂçÂÂæÂÂæ¥询 SQL ãÂÂ
// æªæ¾å° userï¼Âæ ¹æ®æ¡件å Assign å±Âæ§åÂÂ建记å½Â
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
// user -> User{ID: 112, Name: "non_existing", Age: 20}
// æ¾å°亠`name` = `jinzhu` ç userï¼ÂÃ¥ÂÂ忽çÂÂ¥ Attrs
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "jinzhu", Age: 18}
ä¸Â管æ¯å¦æ¾å°记å½Âï¼ÂAssign
é½ä¼Âå°Âå±Âæ§èµÂå¼绠structï¼Â并å°Âç»ÂæÂÂÃ¥ÂÂÃ¥ÂÂæ°æ®åºÂ
// æªæ¾å° userï¼Âæ ¹æ®æ¡件å Assign å±Âæ§åÂÂ建记å½Â
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
// user -> User{ID: 112, Name: "non_existing", Age: 20}
// æ¾å°亠`name` = `jinzhu` ç userï¼Âä¾Âç¶ä¼Âæ ¹æ® Assign æ´æ°记å½Â
db.Where(User{Name: "jinzhu"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// UPDATE users SET age=20 WHERE id = 111;
// user -> User{ID: 111, Name: "jinzhu", Age: 20}
é«Â级æ¥询
Ã¥ÂÂæ¥询
åº亠*gorm.expr
çÂÂÃ¥ÂÂæ¥询
db.Where("amount > (?)", db.Table("orders").Select("AVG(amount)")).Find(&orders)
// SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");
subQuery := db.Select("AVG(age)").Where("name LIKE ?", "name%").Table("users")
db.Select("AVG(age) as avgage").Group("name").Having("AVG(age) > (?)", subQuery).Find(&results)
// SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")
From Ã¥ÂÂæ¥询
GORM Ã¥Â
Â许æ¨å¨ Table
æ¹æ³Âä¸ÂéÂÂè¿ FROM Ã¥ÂÂå¥使ç¨åÂÂæ¥询ï¼Âä¾Âå¦Âï¼Â
db.Table("(?) as u", db.Model(&User{}).Select("name", "age")).Where("age = ?", 18).Find(&User{})
// SELECT * FROM (SELECT `name`,`age` FROM `users`) as u WHERE `age` = 18
subQuery1 := db.Model(&User{}).Select("name")
subQuery2 := db.Model(&Pet{}).Select("name")
db.Table("(?) as u, (?) as p", subQuery1, subQuery2).Find(&User{})
// SELECT * FROM (SELECT `name` FROM `users`) as u, (SELECT `name` FROM `pets`) as p
éÂÂæ©åÂÂ段
Selectï¼ÂæÂÂå®Âä½ æ³ä»Âæ°æ®åºÂä¸Âæ£Âç´¢åºçÂÂÃ¥ÂÂ段ï¼Âé»Â认ä¼ÂéÂÂæ©堨é¨åÂÂ段ãÂÂ
db.Select("name, age").Find(&users)
//// SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
//// SELECT name, age FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
//// SELECT COALESCE(age,'42') FROM users;
说æÂÂï¼Â
.Select("COALESCE(age, ?)", 42)
: è¿Âæ¯æÂÂå®Âæ¥询çÂÂÃ¥ÂÂ段ãÂÂå¨è¿ÂéÂÂ使ç¨äºÂCOALESCE
å½æ°ï¼Âå®Âæ¯ä¸Â个 SQL å½æ°ï¼Âç¨äºÂå¨ç»ÂæÂÂéÂÂä¸ÂéÂÂæ©第ä¸Â个é NULL çÂÂå¼ãÂÂage
æ¯åÂÂ段åÂÂï¼Âå¦ÂæÂÂage
Ã¥ÂÂ段çÂÂå¼为 NULLï¼ÂÃ¥ÂÂä¼ÂéÂÂæ©åÂÂé¢æÂÂä¾ÂçÂÂæ¿代å¼42
ãÂÂå æ¤ï¼Â该æ¥询å°Âä¼Âè¿Âå “users” 表ä¸Âæ¯Âè¡Âç “age” Ã¥ÂÂ段å¼ï¼Âå¦Âæ “age” Ã¥ÂÂ段为 NULLï¼ÂÃ¥ÂÂè¿Âå 42ãÂÂ
type User struct {
ID uint
Name string
Age int
Gender string
// Ã¥ÂÂ设åÂÂé¢è¿ÂæÂÂå ç¾个åÂÂ段...
}
type APIUser struct {
ID uint
Name string
}
// æ¥询æ¶ä¼Âèªå¨éÂÂæ© `id`, `name` Ã¥ÂÂ段
db.Model(&User{}).Limit(10).Find(&APIUser{})
// SELECT `id`, `name` FROM `users` LIMIT 10
注æÂÂ
QueryFields
模å¼Âä¼Âæ ¹æ®å½Âå model çÂÂæÂÂæÂÂÃ¥ÂÂ段åÂÂ称è¿Âè¡ selectãÂÂ
æÂÂåºÂ
Orderï¼ÂæÂÂå®Âä»Âæ°æ®åºÂä¸Âæ£Âç´¢åº记å½ÂçÂÂ顺åºÂãÂÂ设置第äºÂ个åÂÂæ° reorder 为 true
ï¼Âå¯以è¦ÂçÂÂÃ¥ÂÂé¢å®Âä¹ÂçÂÂæÂÂåºÂæ¡件ãÂÂ
db.Order("age desc, name").Find(&users)
//// SELECT * FROM users ORDER BY age desc, name;
// å¤ÂÃ¥ÂÂ段æÂÂåºÂ
db.Order("age desc").Order("name").Find(&users)
//// SELECT * FROM users ORDER BY age desc, name;
// è¦ÂçÂÂæÂÂåºÂ
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
//// SELECT * FROM users ORDER BY age desc; (users1)
//// SELECT * FROM users ORDER BY age; (users2)
æ°éÂÂÃ¥ÂÂÃ¥ÂÂ移
Limitï¼ÂæÂÂå®Âä»Âæ°æ®åºÂæ£Âç´¢åºçÂÂæÂÂ大记å½Âæ°ãÂÂOffsetï¼ÂæÂÂå®Âå¼Âå§Âè¿ÂÃ¥ÂÂè®°å½ÂÃ¥ÂÂè¦Âè·³è¿ÂçÂÂè®°å½Âæ°ãÂÂ
db.Limit(3).Find(&users)
// SELECT * FROM users LIMIT 3;
// Cancel limit condition with -1
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
// SELECT * FROM users LIMIT 10; (users1)
// SELECT * FROM users; (users2)
db.Offset(3).Find(&users)
// SELECT * FROM users OFFSET 3;
db.Limit(10).Offset(5).Find(&users)
// SELECT * FROM users OFFSET 5 LIMIT 10;
// Cancel offset condition with -1
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
// SELECT * FROM users OFFSET 10; (users1)
// SELECT * FROM users; (users2)
æÂȾ°
Countï¼Â该 model è½è·åÂÂçÂÂè®°å½ÂæÂȾ°ãÂÂ
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
//// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)
//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)
db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
//// SELECT count(*) FROM users WHERE name = 'jinzhu'; (count)
db.Table("deleted_users").Count(&count)
//// SELECT count(*) FROM deleted_users;
db.Table("deleted_users").Select("count(distinct(name))").Count(&count)
//// SELECT count( distinct(name) ) FROM deleted_users; (count)
注æ Count
å¿Â
é¡»æ¯é¾å¼Âæ¥询çÂÂæÂÂÃ¥ÂÂä¸Â个æÂÂä½ ï¼Âå 为å®Âä¼Âè¦ÂçÂÂÃ¥ÂÂé¢ç SELECT
ï¼Âä½Âå¦ÂæÂÂéÂÂé¢使ç¨亠count
æ¶ä¸Âä¼Âè¦ÂçÂÂ
Group & Having
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
for rows.Next() {
...
}
// 使ç¨Scanå°Âå¤Âæ¡ç»ÂæÂÂæ«æÂÂè¿ÂäºÂÃ¥Â
ÂÃ¥ÂÂå¤Â好çÂÂç»ÂæÂÂä½ÂÃ¥ÂÂçÂÂä¸Â
type Result struct {
Date time.Time
Total int
}
var rets []Result
db.Table("users").Select("date(created_at) as date, sum(age) as total").Group("date(created_at)").Scan(&rets)
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
for rows.Next() {
...
}
type Result struct {
Date time.Time
Total int64
}
db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
Distinct
ä»Â模åÂÂä¸ÂéÂÂæ©ä¸ÂÃ¥ÂÂçÂÂå¼
db.Distinct("name", "age").Order("name, age desc").Find(&results)
Distinct
works with Pluck
and Count
too.
è¿ÂæÂÂ¥
Joinsï¼ÂæÂÂå®Âè¿ÂæÂ¥æ¡件
type result struct {
Name string
Email string
}
db.Model(&User{}).Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&result{})
// SELECT users.name, emails.email FROM `users` left join emails on emails.user_id = users.id
rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows()
for rows.Next() {
...
}
db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
// multiple joins with parameter
db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
Pluck
Pluckï¼Âæ¥询 model ä¸ÂçÂÂä¸Â个åÂÂä½Â为åÂÂçÂÂï¼Âå¦ÂæÂÂæ¨æ³è¦Âæ¥询å¤Â个åÂÂï¼Âæ¨åºÂ该使ç¨ Scan
var ages []int64
db.Find(&users).Pluck("age", &ages)
var names []string
db.Model(&User{}).Pluck("name", &names)
db.Table("deleted_users").Pluck("name", &names)
// æ³æ¥询å¤Â个åÂÂ段@è¿Âæ ·åÂÂï¼Â
db.Select("name, age").Find(&users)
æ«æÂÂ
Scanï¼Âæ«æÂÂç»ÂæÂÂè³ä¸Â个 struct.
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", "Antonio").Scan(&result)
var results []Result
db.Table("users").Select("name, age").Where("id > ?", 0).Scan(&results)
// Ã¥ÂÂç SQL
db.Raw("SELECT name, age FROM users WHERE name = ?", "Antonio").Scan(&result)
Count
Count ç¨äºÂè·åÂÂå¹é ÂçÂÂè®°å½Âæ°
var count int64
db.Model(&User{}).Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Count(&count)
// SELECT count(1) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'
db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
// SELECT count(1) FROM users WHERE name = 'jinzhu'; (count)
db.Table("deleted_users").Count(&count)
// SELECT count(1) FROM deleted_users;
// Count with Distinct
db.Model(&User{}).Distinct("name").Count(&count)
// SELECT COUNT(DISTINCT(`name`)) FROM `users`
db.Table("deleted_users").Select("count(distinct(name))").Count(&count)
// SELECT count(distinct(name)) FROM deleted_users
// Count with Group
users := []User{
{Name: "name1"},
{Name: "name2"},
{Name: "name3"},
{Name: "name3"},
}
db.Model(&User{}).Group("name").Count(&count)
count // => 3
é¾å¼ÂæÂÂä½Âç¸堳
é¾å¼ÂæÂÂä½Â
Method Chainingï¼ÂGorm å®Âç°äºÂé¾å¼ÂæÂÂä½ÂæÂ¥å£ï¼ÂæÂÂ以你å¯以æÂÂ代ç ÂÃ¥ÂÂæÂÂè¿Âæ ·ï¼Â
// Ã¥ÂÂ建ä¸Â个æ¥询
tx := db.Where("name = ?", "jinzhu")
// æ·»å æ´å¤Âæ¡件
if someCondition {
tx = tx.Where("age = ?", 20)
} else {
tx = tx.Where("age = ?", 30)
}
if yetAnotherCondition {
tx = tx.Where("active = ?", 1)
}
å¨è°Âç¨ç«Âå³æ§è¡Âæ¹æ³ÂÃ¥ÂÂä¸Âä¼ÂçÂÂæÂÂQuery
è¯Âå¥ï¼ÂÃ¥ÂÂå©è¿Â个ç¹æ§你å¯以åÂÂ建ä¸Â个å½æ°æÂ¥å¤ÂçÂÂä¸ÂäºÂéÂÂç¨é»è¾ÂãÂÂ
ç«Âå³æ§è¡Âæ¹æ³Â
Immediate methods ï¼Âç«Âå³æ§è¡Âæ¹æ³Âæ¯æÂÂé£äºÂä¼Âç«Âå³çÂÂæÂÂSQL
è¯Âå¥并åÂÂéÂÂå°æ°æ®åºÂçÂÂæ¹æ³Â, ä»Â们ä¸Â辯CRUD
æ¹æ³Âï¼Âæ¯Âå¦Âï¼Â
Create
, First
, Find
, Take
, Save
, UpdateXXX
, Delete
, Scan
, Row
, Rows
â¦
è¿ÂæÂÂä¸Â个åºäºÂä¸Âé¢é¾å¼Âæ¹æ³Â代ç ÂçÂÂç«Âå³æ§è¡Âæ¹æ³ÂçÂÂä¾ÂÃ¥ÂÂï¼Â
tx.Find(&user)
çÂÂæÂÂçÂÂSQLè¯Âå¥å¦Âä¸Âï¼Â
SELECT * FROM users where name = 'jinzhu' AND age = 30 AND active = 1;
èÂÂå´
Scopes
ï¼ÂScopeæ¯建ç«Âå¨é¾å¼ÂæÂÂä½ÂçÂÂåºç¡Âä¹Âä¸ÂçÂÂãÂÂ
åºäºÂå®Âï¼Âä½ å¯以æ½åÂÂä¸ÂäºÂéÂÂç¨é»è¾Âï¼ÂÃ¥ÂÂåºæ´å¤Âå¯éÂÂç¨çÂÂå½æ°åºÂãÂÂ
func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
return db.Where("amount > ?", 1000)
}
func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
return db.Where("pay_mode_sign = ?", "C")
}
func PaidWithCod(db *gorm.DB) *gorm.DB {
return db.Where("pay_mode_sign = ?", "C")
}
func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
return func (db *gorm.DB) *gorm.DB {
return db.Scopes(AmountGreaterThan1000).Where("status IN (?)", status)
}
}
db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
// æÂ¥æ¾æÂÂæÂÂéÂÂé¢Â大亠1000 çÂÂä¿¡ç¨å¡订åÂÂ
db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
// æÂ¥æ¾æÂÂæÂÂéÂÂé¢Â大亠1000 ç COD 订åÂÂ
db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
// æÂ¥æ¾æÂÂæÂÂéÂÂé¢Â大亠1000 ä¸Âå·²ä»Â款æÂÂèÂÂ
å·²åÂÂè´§çÂÂ订åÂÂ
å¤Â个ç«Âå³æ§è¡Âæ¹æ³Â
Multiple Immediate Methodsï¼Âå¨ GORM ä¸Â使ç¨å¤Â个ç«Âå³æ§è¡Âæ¹æ³Âæ¶ï¼ÂÃ¥ÂÂä¸Â个ç«Âå³æ§è¡Âæ¹æ³Âä¼Âå¤Âç¨åÂÂä¸Â个ç«Âå³æ§è¡Âæ¹æ³ÂçÂÂæ¡件 (ä¸Âå æŒ èÂÂæ¡件) ãÂÂ
db.Where("name LIKE ?", "jinzhu%").Find(&users, "id IN (?)", []int{1, 2, 3}).Count(&count)
çÂÂæÂÂç Sql
SELECT * FROM users WHERE name LIKE 'jinzhu%' AND id IN (1, 2, 3)
SELECT count(*) FROM users WHERE name LIKE 'jinzhu%'
æ´æ°
ä¿ÂÃ¥ÂÂæÂÂæÂÂÃ¥ÂÂ段
Save()
é»Â认ä¼Âæ´æ°该对象çÂÂæÂÂæÂÂÃ¥ÂÂ段ï¼Âå³使你没æÂÂèµÂå¼ãÂÂ
db.First(&user)
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
æ´æ°åÂÂ个åÂÂ
// Update with conditions
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;
// User's ID is `111`:
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
// Update with conditions and model value
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;
æ´æ°å¤ÂÃ¥ÂÂ
// Update attributes with `struct`, will only update non-zero fields
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// Update attributes with `map`
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
注æÂÂ: å½Â使ç¨ struct æ´æ°æ¶ï¼ÂGORM å°Âåªæ´æ°éÂÂé¶åÂÂ段ãÂÂæ¨å¯è½å¸ÂæÂÂ使ç¨
map
æ´æ°å±Âæ§æÂÂ使ç¨Select
æÂÂå®Âè¦Âæ´æ°çÂÂÃ¥ÂÂ段
æ Hooksæ´æ°
ä¸Âé¢çÂÂæ´æ°æÂÂä½Âä¼Âèªå¨è¿Âè¡ model ç BeforeUpdate
, AfterUpdate
æ¹æ³Âï¼Âæ´æ° UpdatedAt
æ¶é´æ³, å¨æ´æ°æ¶ä¿ÂÃ¥ÂÂÃ¥Â
¶ Associations
, å¦ÂæÂÂä½ ä¸Âæ³è°Âç¨è¿ÂäºÂæ¹æ³Âï¼Âä½ å¯以使ç¨ UpdateColumn
ï¼ UpdateColumns
// æ´æ°åÂÂ个å±Âæ§ï¼Â类似亠`Update`
db.Model(&user).UpdateColumn("name", "hello")
//// UPDATE users SET name='hello' WHERE id = 111;
// æ´æ°å¤Â个å±Âæ§ï¼Â类似亠`Updates`
db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18 WHERE id = 111;
æ¹éÂÂæ´æ°
å¦ÂæÂÂæÂÂ们没æÂÂ使ç¨ Model æÂÂå®Â主é®å¼çÂÂè®°å½Âï¼ÂGORM å°Âæ§è¡Âæ¹éÂÂæ´æ°ï¼Âæ¹éÂÂæ´æ°æ¶Hooksï¼Âé©åÂÂå½æ°ï¼Â
ä¸Âä¼Âè¿Âè¡ÂãÂÂ
// Update with struct
db.Model(User{}).Where("role = ?", "admin").Updates(User{Name: "hello", Age: 18})
// UPDATE users SET name='hello', age=18 WHERE role = 'admin';
// Update with map
db.Table("users").Where("id IN ?", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})
// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);
// 使ç¨ `RowsAffected` è·åÂÂæ´æ°记å½ÂæÂȾ°
db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected
使ç¨SQL表达å¼Âæ´æ°
å Âæ¥询表ä¸ÂçÂÂ第ä¸Âæ¡æ°æ®ä¿ÂÃ¥ÂÂè³userÃ¥ÂÂéÂÂãÂÂ
var user User
db.First(&user)
db.Model(&user).Update("age", gorm.Expr("age * ? + ?", 2, 100))
//// UPDATE `users` SET `age` = age * 2 + 100, `updated_at` = '2020-02-16 13:10:20' WHERE `users`.`id` = 1;
db.Model(&user).Updates(map[string]interface{}{"age": gorm.Expr("age * ? + ?", 2, 100)})
//// UPDATE "users" SET "age" = age * '2' + '100', "updated_at" = '2020-02-16 13:05:51' WHERE `users`.`id` = 1;
db.Model(&user).UpdateColumn("age", gorm.Expr("age - ?", 1))
//// UPDATE "users" SET "age" = age - 1 WHERE "id" = '1';
db.Model(&user).Where("age > 10").UpdateColumn("age", gorm.Expr("age - ?", 1))
//// UPDATE "users" SET "age" = age - 1 WHERE "id" = '1' AND quantity > 10;
ä¿®æ¹Hooksä¸ÂçÂÂå¼
å¦ÂæÂÂä½ æ³修æ¹ BeforeUpdate
, BeforeSave
ç Hooks ä¸Âæ´æ°çÂÂå¼ï¼Âä½ å¯以使ç¨ scope.SetColumn
, ä¾Âå¦Âï¼Â
func (user *User) BeforeSave(scope *gorm.Scope) (err error) {
if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil {
scope.SetColumn("EncryptedPassword", pw)
}
}
å ¶å®Âæ´æ°éÂÂ项
// 为 update SQL æ·»å åÂ
¶å®Âç SQL
db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name", "hello")
//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);
å é¤
å é¤记å½Â
è¦å å é¤记å½Âæ¶ï¼Â请确ä¿Â主é®åÂÂ段æÂÂå¼ï¼ÂGORM ä¼ÂéÂÂè¿Â主é®åÂȌ é¤记å½Âï¼Âå¦ÂæÂÂ主é®为空ï¼ÂGORM ä¼Âå é¤该 model çÂÂæÂÂæÂÂè®°å½ÂãÂÂ
// å é¤ç°æÂÂè®°å½Â
db.Delete(&email)
//// DELETE from emails where id=10;
db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;
db.Delete(&User{}, "10")
// DELETE FROM users WHERE id = 10;
db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);
// 带é¢Âå¤Âæ¡件çÂÂå é¤
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
// 为å é¤ SQL æ·»å é¢Âå¤Âç SQL æÂÂä½Â
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
æ¹éÂÂå é¤
å¦ÂæÂÂæÂÂå®ÂçÂÂå¼ä¸Âå æ¬主å±Âæ§ï¼Âé£习GORM ä¼Âæ§è¡Âæ¹éÂÂå é¤ï¼Âå®Âå°Âå é¤æÂÂæÂÂå¹é ÂçÂÂè®°å½ÂãÂÂ
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
//// DELETE from emails where email LIKE "%jinzhu%";
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
//// DELETE from emails where email LIKE "%jinzhu%";
å¯以å°Âä¸Â个主é®åÂÂçÂÂä¼ éÂÂç»ÂDelete
æ¹æ³Âï¼Â以便æ´é«ÂæÂÂçÂÂå é¤æ°æ®éÂÂ大çÂÂè®°å½Â
var users = []User{{ID: 1}, {ID: 2}, {ID: 3}}
db.Delete(&users)
// DELETE FROM users WHERE id IN (1,2,3);
db.Delete(&users, "name LIKE ?", "%jinzhu%")
// DELETE FROM users WHERE name LIKE "%jinzhu%" AND id IN (1,2,3);
软å é¤
å¦ÂæÂÂä¸Â个 model æ DeletedAt
Ã¥ÂÂ段ï¼Âä»Âå°Âèªå¨è·å¾Â软å é¤çÂÂÃ¥ÂÂè½@å½Âè°Âç¨ Delete
æ¹æ³Âæ¶@记å½Âä¸Âä¼ÂçÂÂæ£çÂÂä»Âæ°æ®åºÂä¸Â被å é¤@åªä¼Âå°ÂDeletedAt
Ã¥ÂÂ段çÂÂå¼ä¼Â被设置为å½ÂÃ¥ÂÂæ¶é´
db.Delete(&user)
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
// æ¹éÂÂå é¤
db.Where("age = ?", 20).Delete(&User{})
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
// æ¥询记å½Âæ¶ä¼Â忽ç¥被软å é¤çÂÂè®°å½Â
db.Where("age = 20").Find(&user)
//// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
// Unscoped æ¹æ³Âå¯以æ¥询被软å é¤çÂÂè®°å½Â
db.Unscoped().Where("age = 20").Find(&users)
//// SELECT * FROM users WHERE age = 20;
å¦ÂæÂÂ你并ä¸Âæ³åµÂå¥Âgorm.Model
ï¼Âä½ ä¹Âå¯以åÂÂä¸Âæ¹ä¾ÂÃ¥ÂÂé£样å¼Âå¯软å é¤ç¹æ§ï¼Â
type User struct {
ID int
Deleted gorm.DeletedAt
Name string
}
永习å é¤
// Unscoped æ¹æ³Âå¯以ç©çÂÂå é¤记å½Â
db.Unscoped().Delete(&order)
//// DELETE FROM orders WHERE id=10;