使ç¨ GORMï¼ÂGo ç ORM åºÂï¼Âè¿ÂæÂ¥æ°æ®åºÂï¼Â并å®Âç°å¢Âå æ¹æÂ¥æÂÂä½Â
Ã¥ÂÂè¨Â
é¢åÂÂç¨æ·
- æÂÂæ¡ Go è¯Âè¨Âåºç¡Â
- äºÂ解 MySQLæ°æ®åºÂ
ç¬Âè ç¯å¢Â
- macos 10.15.7
- Golang 1.18
- GoLand 2022.01
- Mysql 8.0.20
读å®Âæ¾ÂÂå¯以è·å¾Â
- äºÂ解ORMæ¡Âæ¶çÂÂå®Âä¹Â
- çÂÂæÂÂ使ç¨GORMå è¿Âè¡ÂåºæÂÂCRUD
å¼Âç¨
GORM æÂÂå | GORM – The fantastic ORM library for Golang, aims to be developer friendly.
ä¸ÂãÂÂä»Âç»Â
GORMæ¯Goè¯Âè¨ÂçÂÂä¸Â个ORM(Object Relational Mapping)åºÂãÂÂå®Âå¯以让æÂÂ们éÂÂè¿ÂGoæÂ¥æÂÂä½Âæ°æ®åºÂä¸ÂçÂÂæ°æ®ãÂÂ
ORMå³对象堳系æ å°Âï¼Âå°Âæ°æ®åºÂä¸ÂçÂÂ表转为ç¨ÂåºÂä¸ÂçÂÂå®Âä½Â对象ï¼ÂéÂÂè¿Â建ç«Â对象åÂÂ堳系æ°æ®ä¹Âé´çÂÂæ å°Â模åÂÂï¼Âå¯以å°Âä¸Â个表对åºÂä¸Â个å®Âä½Âç±»ï¼Âå°Âä¸Âæ¡记å½Â对åºÂä¸Â个对象ãÂÂï¼ÂéÂÂè¿Â使ç¨é¢åÂÂ对象æ¹å¼ÂæÂ¥æÂÂä½Âæ°æ®åºÂï¼Âå¯以ç®ÂÃ¥ÂÂå¼ÂÃ¥ÂÂï¼ÂÃ¥ÂÂå°ÂéÂÂå¤Âå³å¨ãÂÂ
1.1 ç¹æ§
- å ¨åÂÂè½ ORM
- å ³è (Has Oneï¼ÂHas Manyï¼ÂBelongs Toï¼ÂMany To Manyï¼Âå¤ÂæÂÂï¼ÂÃ¥ÂÂ表继æ¿)
- Createï¼ÂSaveï¼ÂUpdateï¼ÂDeleteï¼ÂFind ä¸Âé©åÂÂæ¹æ³Â
- æ¯æÂÂ
Preload
ãÂÂJoins
çÂÂé¢Âå 载 - äºÂå¡ï¼ÂåµÂå¥ÂäºÂå¡ï¼ÂSave Pointï¼ÂRollback To Saved Point
- Contextï¼Âé¢Âç¼Âè¯Â模å¼Âï¼ÂDryRun 模å¼Â
- æ¹éÂÂæÂÂå ¥ï¼ÂFindInBatchesï¼ÂFind/Create with Mapï¼Â使ç¨ SQL 表达å¼ÂãÂÂContext Valuer è¿Âè¡ CRUD
- SQL æÂÂ建å¨ï¼ÂUpsertï¼Âæ°æ®åºÂéÂÂï¼ÂOptimizer/Index/Comment Hintï¼Âå½åÂÂÃ¥ÂÂæ°ï¼ÂÃ¥ÂÂæ¥询
- å¤ÂÃ¥ÂÂ主é®ï¼Âç´¢å¼Âï¼Â约æÂÂ
- Auto Migration
- èªå®Âä¹ Logger
- çµ活çÂÂå¯æ©å±ÂæÂÂ件 APIï¼ÂDatabase Resolverï¼Âå¤Âæ°æ®åºÂï¼Â读åÂÂÃ¥ÂÂ离ï¼ÂãÂÂPrometheusâ¦
- æ¯Â个ç¹æ§é½ç»Âè¿ÂäºÂæµÂè¯ÂçÂÂéÂÂéÂÂèÂÂéªÂ
- å¼ÂÃ¥ÂÂè åÂÂ好
1.2 使ç¨æ¥骤
- å¨MySQLæÂÂå ¶ä»Âæ°æ®åºÂä¸Âå ÂÃ¥ÂÂ建SchemaãÂÂ
- 使ç¨GORMå°ÂGoç»ÂæÂÂä½Âæ å°Âå°æ°æ®åºÂ表ï¼Âæ¯Âå¦Âå®Âä¹Âä¸Â个Userç»ÂæÂÂä½Âæ å°Âå°user表ãÂÂ
- å¨Go代ç Âä¸Âï¼ÂæÂÂ们就å¯以æÂÂä½Âé£个ç»ÂæÂÂä½Âï¼ÂèÂÂGORMä¼Âå¨åÂÂå°èªå¨转æ¢为对åºÂçÂÂSQLå½令ï¼ÂæÂÂ¥crudæ°æ®åºÂ表ä¸ÂçÂÂæ°æ®ãÂÂ
- ä¹Âå¯以ç´æÂ¥å¨Go代ç Âä¸Âç¨GORMçÂÂAPIæÂÂé SQLæ¥询æ°æ®åºÂãÂÂ
1.3 å®Âè£Â
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
1.4 导åÂÂ
å¨使ç¨GORMè¿ÂæÂ¥æ°æ®åºÂæ¶ï¼ÂéÂÂè¦Â导堥两个åÂÂ
- gormæ ¸å¿ÂåºÂ
import "gorm.io/gorm"
è¿Â个å æÂÂä¾ÂäºÂGORMçÂÂæ ¸å¿ÂÃ¥ÂÂè½åÂÂAPIãÂÂ
- æ°æ®åºÂ驱å¨
import "gorm.io/driver/mysql"
è¿Â个å æÂÂä¾ÂäºÂGORMä¸ÂMySQLæ°æ®åºÂçÂÂ交äºÂãÂÂ
GORM å®Âæ¹æ¯æ sqlite
ãÂÂmysql
ãÂÂpostgres
ãÂÂsqlserver
ãÂÂå¦ÂæÂÂè¦Âè¿ÂæÂ¥åÂ
¶ä»Âç±»åÂÂçÂÂæ°æ®åºÂï¼Âå¯以å¤Âç¨/èªè¡Âå¼ÂÃ¥ÂÂ驱å¨ãÂÂç¼ÂÃ¥ÂÂ驱å¨ | GORM – The fantastic ORM library for Golang, aims to be developer friendly.
1.5 dsn
dsn(data source name)å°±æ¯æ°æ®åºÂçÂÂè¿ÂæÂ¥é Â置信æ¯ï¼Âå å«äºÂè¿ÂæÂ¥æ°æ®åºÂéÂÂè¦ÂçÂÂæÂÂæÂÂÃ¥ÂÂæ°ãÂÂ
username:password@protocol(address)/dbname?parameters
dsnéÂÂ常ç±以ä¸Âé¨åÂÂç»ÂæÂÂï¼Â
- username:password – æ°æ®åºÂçÂÂç¨æ·åÂÂÃ¥ÂÂå¯Âç Â
- @tcp(127.0.0.1:3306) – æ°æ®åºÂçÂÂIPå°åÂÂÃ¥ÂÂ端å£
- /dbname – è¿ÂæÂ¥çÂÂæ°æ®åºÂÃ¥ÂÂ
- charset=utf8mb4 – Ã¥ÂÂ符éÂÂç¼Âç Â
- parseTime=True – æ¯å¦解æÂÂæ¶é´类åÂÂï¼Âå¦ÂæÂÂæ³è¦Âæ£确çÂÂå¤ÂçÂÂ
time.Time
ï¼ÂÃ¥ÂÂä¸Âå®ÂéÂÂè¦Â带ç - loc=Local – æ¶é´ä½Â置信æ¯
æÂÂ们å¯以æÂÂè¿ÂæÂ¥æ°æ®åºÂéÂÂè¦ÂçÂÂæÂÂæÂÂé Â置信æ¯é½éÂÂè¿ÂdsnÃ¥ÂÂ符串传éÂÂç»Â驱å¨ï¼Âç¶åÂÂ驱å¨ä¼Âæ ¹æ®dsnä¸ÂçÂÂÃ¥ÂÂæ°å¼ï¼ÂÃ¥ÂÂæ°æ®åºÂè¿Âè¡Â交äºÂï¼Â建ç«Âè¿ÂæÂ¥ãÂÂ
MySQLè¿Âæ¥示ä¾Âï¼Â
dsn := "myuser:mypass@tcp(127.0.0.1:3306)/mydb?charset=utf8mb4&parseTime=True&loc=Local"
1.6 GORM约å®Â
GORM å¾åÂÂäºÂ约å®Âï¼ÂèÂÂä¸Âæ¯é Âç½®ãÂÂ
1.6.1 å½åÂÂ约å®Â
é»Â认æÂÂ
åµä¸Âï¼ÂGORM 使ç¨ ID
ä½Â为主é®ï¼Â使ç¨ç»ÂæÂÂä½ÂÃ¥ÂÂç èÂÂå½¢å¤Âæ°
ä½Â为表åÂÂï¼ÂÃ¥ÂÂ段åÂÂç èÂÂå½¢
ä½Â为åÂÂÃ¥ÂÂï¼Â并使ç¨ CreatedAt
ãÂÂUpdatedAt
Ã¥ÂÂ段追踪åÂÂ建ãÂÂæ´æ°æ¶é´ãÂÂ
è¿ÂéÂÂèÂÂå½¢å¤Âæ°
æÂÂçÂÂæ¯:
- èÂÂå½¢(snake case)ï¼ÂÃ¥ÂÂæ¯Âå ¨é¨å°ÂÃ¥ÂÂ,Ã¥ÂÂè¯Âä¹Âé´ç¨_Ã¥ÂÂéÂÂãÂÂå¦Âuser_name
- å¤Âæ°æ¯å¨èÂÂå½¢åºç¡Âä¸Âï¼ÂÃ¥ÂÂ转æ¢为å¤Âæ°形å¼ÂãÂÂå¦Âuser_names
ä¾Âå¦Âï¼Â
- ç»ÂæÂÂä½Âå UserInfo
- 表åÂÂä¼Âæ å°Â为 user_infos (èÂÂå½¢å¤Âæ°)
- Ã¥ÂÂ段 UserName
- Ã¥ÂÂÃ¥ÂÂä¼Âæ å°Â为 user_name (èÂÂ形形å¼Â)
- Ã¥ÂÂ段 ID
- Ã¥ÂÂÃ¥ÂÂä¼Âæ å°Â为 id (èÂÂ形形å¼Â)ï¼Â并ä¼Âä½Â为主é®
1.6.2 æ¶é´æ³追踪
CreatedAt
对äºÂæ CreatedAt
Ã¥ÂÂ段çÂÂ模åÂÂï¼ÂÃ¥ÂÂ建记å½Âæ¶ï¼Âå¦ÂæÂÂ该åÂÂ段å¼为é¶å¼ï¼ÂÃ¥ÂÂå°Â该åÂÂ段çÂÂå¼设为å½ÂÃ¥ÂÂæ¶é´
db.Create(&user) // å° `CreatedAt` 设为å½ÂÃ¥ÂÂæ¶é´
user2 := User{Name: "Alex", CreatedAt: time.Now()}
db.Create(&user2) // user2 ç `CreatedAt` ä¸Âä¼Â被修æ¹
// æ³è¦Âä¿®æ¹该å¼ï¼Âæ¨å¯以使ç¨ `Update`
db.Model(&user).Update("CreatedAt", time.Now())
UpdatedAt
对äºÂæ UpdatedAt
Ã¥ÂÂ段çÂÂ模åÂÂï¼Âæ´æ°记å½Âæ¶ï¼Âå°Â该åÂÂ段çÂÂå¼设为å½ÂÃ¥ÂÂæ¶é´ãÂÂ
db.Save(&user) // å° `UpdatedAt` 设为å½ÂÃ¥ÂÂæ¶é´
user3 := User{Name: "Alex", UpdatedAt: time.Now()}
db.Save(&user3) // æ´æ°æ¶ï¼Âuser3 ç `UpdatedAt` ä¼Âä¿®æ¹为å½ÂÃ¥ÂÂæ¶é´
db.Model(&user).Update("name", "Alex") // ä¼Âå° `UpdatedAt` 设为å½ÂÃ¥ÂÂæ¶é´
db.Model(&user).UpdateColumn("name", "Alex") // `UpdatedAt` ä¸Âä¼Â被修æ¹
1.7 gorm.Model
gorm.Modelæ¯ä¸Â个GORMä¸ÂæÂÂä¾ÂçÂÂå 置模åÂÂï¼Âå å«ä¸ÂäºÂ常ç¨åÂÂ段,å¯以å åµÂå°èªå®Âä¹Â模åÂÂä¸Â使ç¨ãÂÂ
gorm.Modelå®Âä¹Âå¦Âä¸Âï¼Â
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
å®Âå å«以ä¸ÂÃ¥ÂÂ段ï¼Â
- IDï¼Âç±»åÂÂ为uintçÂÂ主é®
- CreatedAtï¼Âè®°å½Âé¦Â次åÂÂ建æ¶é´
- UpdatedAtï¼Âè®°å½Âæ¯Â次æ´æ°æ¶é´
- DeletedAtï¼Â软å é¤æ¶é´
å åµÂgorm.ModelæÂÂä¾ÂçÂÂ好å¤Âï¼Â
- èªå¨è·å¾ÂéÂÂç¨åÂÂ段IDï¼ÂCreatedAtçÂÂï¼Âæ éÂÂéÂÂå¤Âå®Âä¹Â
- IDÃ¥ÂÂ段èªå¨æÂÂ为主é®
- CreatedAtÃ¥ÂÂUpdatedAtèªå¨记å½Âæ¶é´
- è·åÂÂ软å é¤åÂÂè½
使ç¨æ¶æÂÂ们å¯以å¨模åÂÂä¸ÂåµÂå ¥ï¼Â
type User struct {
gorm.Model
Name string
}
User模åÂÂå°Âèªå¨è·å¾Âgorm.ModelçÂÂéÂÂç¨åÂÂ段åÂÂè¡Â为ï¼ÂéÂÂ常æ¹便ãÂÂ
1.8 åµÂå ¥ç»ÂæÂÂä½Â
对äºÂå¿åÂÂÃ¥ÂÂ段ï¼ÂGORM ä¼Âå°Âå ¶åÂÂ段å å«å¨ç¶ç»ÂæÂÂä½Âä¸Âï¼Âä¾Âå¦Âï¼Â
type User struct {
gorm.Model
Name string
}
// çÂÂæÂÂäºÂ
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
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
}
äºÂãÂÂCRUD
2.1 Ã¥ÂÂ建Schema
éÂÂ常å¨使ç¨GORMæ¶ï¼ÂéÂÂè¿ÂMySQLï¼ÂæÂÂå ¶ä»Âæ°æ®åºÂï¼ DDLÃ¥ÂÂ建表ç»ÂæÂÂï¼Âç¶åÂÂGORMå°ÂGo structæ å°Âå°表ï¼Âè¿Âè¡ÂCURDæÂÂä½ÂãÂÂ
2.1.1 ç»å½ÂMySQL
建议使ç¨æ°æ®åºÂ管çÂÂ工堷è¿Âè¡Â建åºÂ建表ï¼Âå¦ÂNavicatãÂÂDataGripçÂÂ
æ¤å¤ÂéÂÂè¿Âterminalè¿Âè¡Âæ¼Â示
mysql -u root -p #Ã¥ÂÂ车åÂÂï¼Âè¾ÂÃ¥Â
Â¥MySQLçÂÂæ°æ®åºÂå¯Âç Âè¿Âè¡Âç»å½Â
2.1.2 Ã¥ÂÂ建æ°æ®åºÂ
CREATE DATABASE `go_example_db`
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci;
说æÂÂï¼Â
- CREATE DATABASE è¯Âå¥ç¨äºÂÃ¥ÂÂ建æ°æ®åºÂ
- æ°æ®åºÂÃ¥ÂÂç¨åÂÂå¼Âå·å 裹ï¼Âå 为å å«ä¸ÂÃ¥ÂÂ线_
- CHARACTER SET 设置åÂÂ符éÂÂ为utf8mb4
- COLLATE 设置æÂÂåºÂè§ÂÃ¥ÂÂ为utf8mb4_general_ci
utf8mb4æ¯MySQLæ¯æÂÂçÂÂæÂÂ大åÂÂ符éÂÂï¼Â堼容æÂÂæÂÂUTF-8Ã¥ÂÂ符ã general_ci表示大å°ÂÃ¥ÂÂä¸ÂæÂÂæÂÂçÂÂæÂÂåºÂè§ÂÃ¥ÂÂãÂÂ
æÂÂ以以ä¸ÂSQLè¯Âå¥åÂÂ建çÂÂgo_example_dbæ°æ®åºÂæ¯æÂÂ广æ³ÂçÂÂUTF-8æÂÂæ¬ï¼Âä¸ÂæÂÂåºÂÃ¥ÂÂæ¯Âè¾Â对大å°ÂÃ¥ÂÂä¸ÂæÂÂæÂÂãÂÂ
2.1.3 Ã¥ÂÂ建表
use go_example_db; # Ã¥ÂÂæ¢å°go_example_dbæ°æ®åºÂ
CREATE TABLE `users` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`created_at` datetime(3) NOT NULL,
`updated_at` datetime(3) NOT NULL,
`deleted_at` datetime(3) NULL,
`name` varchar(255) NOT NULL,
`age` int unsigned NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
说æÂÂï¼Â
- 表åÂÂ为ç»ÂæÂÂä½Âå¤Âæ°形å¼Âusers
- idÃ¥ÂÂ段为主é®èªå¢Â
- Ã¥ÂÂ建æ¶é´ãÂÂæ´æ°æ¶é´ãÂÂ软å é¤æ¶é´æ å°Â为datetime(3) ï¼Â表示ç§Âå¯以ä¿ÂÃ¥ÂÂ3ä½Âå°Âæ°
- nameæ å°Â为varcharç±»åÂÂ
- é»Â认å¼ÂæÂÂInnoDB,Ã¥ÂÂ符éÂÂutf8mb4,æÂÂåºÂè§ÂÃ¥ÂÂgeneral_ci
è¿Â个DDLÃ¥ÂÂ建çÂÂusers表å¯以å®Âæ´æ å°ÂUserç»ÂæÂÂä½ÂãÂÂ
2.1.4 æ·»å æµÂè¯Âæ°æ®
INSERT INTO `users` (`created_at`, `updated_at`, `deleted_at`, `name`,`age`)
VALUES
('2022-05-01 12:00:00.000', '2022-05-01 12:00:00.000', NULL, 'Abraham',20),
('2022-06-01 08:30:15.123', '2022-06-01 08:30:15.123', NULL, 'Benjamin',30),
('2022-07-01 23:50:55.555', '2022-07-01 23:50:55.555', NULL, 'Captain',21),
('2022-08-01 20:00:00.777', '2022-08-01 20:00:00.777', NULL, 'Dufresne',NULL),
('2022-09-01 16:20:10.520', '2022-09-01 16:20:10.520', NULL, 'Elizabeth',NULL);
æ·»å 5æ¡æµÂè¯Âæ°æ®ç¨äºÂCRUDï¼Âå¦ÂæÂÂéÂÂè¦Âï¼Âå¯èªè¡Âå¢Âå æµÂè¯Âæ°æ®ãÂÂ
2.2 项ç®åºç¡ÂæÂÂ建
2.2.1 导åÂÂ
éÂÂè¦Â导堥gormæ ¸å¿Âå åÂÂMySQL驱å¨åÂÂ
package main
import "gorm.io/gorm"
import "gorm.io/driver/mysql"
func main() {
}
å¨使ç¨å ä¹ÂÃ¥ÂÂï¼Âå¦ÂæÂÂä¹ÂÃ¥ÂÂ没æÂÂå®Â裠è¿Â该ä¾ÂèµÂå ï¼Âè¦Âè®°å¾Âå Âå®Â裠åÂÂ
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
2.2.2 å®Âä¹Âmodel
type User struct {
gorm.Model
Name string
}
2.2.3 è¿ÂæÂ¥æ°æ®åºÂ
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User表ç»ÂæÂÂ
type User struct {
gorm.Model
Name string
Age int
}
// è·åÂÂdbå®Âä¾Â
func getMySqlDB() (*gorm.DB, error) {
dsn := "root:password@tcp(127.0.0.1:3306)/go_example_db?charset=utf8mb4&parseTime=True&loc=Local" // è¿ÂæÂ¥åÂÂ符串ï¼Âå°Âæ¤å¤ÂçÂÂpaawordæ¿æ¢为MySQLçÂÂå¯Âç Â
db, err := gorm.Open( // æÂÂå¼Âæ°æ®åºÂè¿ÂæÂÂ¥
mysql.Open(dsn), // 使ç¨MySQL驱å¨根æ®DSNçÂÂä¿¡æ¯è¿ÂæÂ¥æ°æ®åºÂ
&gorm.Config{
Logger: logger.Default.LogMode(logger.Info), // 设置åÂ
¨å±ÂæÂ¥å¿Â模å¼Â为Infoï¼Âè¿Âæ ·å°±å¯以æÂÂå°sql
}) // Config{}æ¯gorm.ConfigéÂ
Â置信æ¯
// è¿ÂÃ¥ÂÂå®Âä¾ÂdbçÂÂæÂÂéÂÂÃ¥ÂÂå¼Â常
return db, err
}
func main() {
db, err := getMySqlDB()
if err != nil {
panic("failed to connect database")
}
// æÂÂå°å®Âä¾Âdb
println(db)
}
2.3 Create
2.3.1 æ°å¢Âä¸Âæ¡记å½Â
user := User{Name: "Jessica", Age: 24} // Ã¥ÂÂ建ä¸Â个userå®Âä½Â
db.Create(&user) // Ã¥ÂÂ建ä¸Âæ¡记å½Â
println(user.ID) // è®°å½Âæ°å¢ÂÃ¥ÂÂï¼Âä¼Âè¿ÂÃ¥ÂÂæÂÂÃ¥Â
¥æ°æ®çÂÂ主é®并设置å°userå®Âä½Âä¸Â
println(result.Error) // è¿Âå error
println(result.RowsAffected) // è¿ÂÃ¥ÂÂæÂÂÃ¥Â
¥è®°å½ÂçÂÂæ¡æ°
2.3.2 æ¹éÂÂæÂÂå ¥
å°ÂÃ¥ÂÂçÂÂæ°æ®传éÂÂç» Create
æ¹æ³Âï¼ÂGORM å°ÂçÂÂæÂÂä¸Â个åÂÂä¸Âç SQL è¯Âå¥æÂ¥æÂÂÃ¥Â
¥æÂÂæÂÂæ°æ®ï¼Â并åÂÂ填主é®çÂÂå¼ï¼Âé©åÂÂæ¹æ³Âä¹Âä¼Â被è°Âç¨ãÂÂ
var users = []User{{Name: "Alex", Age: 25}, {Name: "Bob", Age: 20}, {Name: "Candy", Age: 25}}
db.Create(&users)
for _, item := range users {
println(item.ID)
}
2.3.3 éÂÂå®ÂÃ¥ÂÂ段åÂÂ建
GORMå¨åÂÂ建记å½Âæ¶ï¼Âä¼Âèªå¨å¤ÂçÂÂæÂÂäºÂç¹æ®ÂÃ¥ÂÂ段ï¼Âæ¯Âå¦Âï¼Â
- æÂÂPrimaryKeyæ Âç¾çÂÂÃ¥ÂÂ段ï¼Âä¼Âèªå¨åÂÂ建ï¼Âå³便ä¸Âå¨Selectä¸Â
- æÂÂDefaultæ Âç¾çÂÂÃ¥ÂÂ段ï¼Âä¹Âä¼Â被èªå¨å¤ÂçÂÂ
- 模åÂÂä¸ÂçÂÂCreatedAtï¼ÂUpdatedAtçÂÂéÂÂç¨åÂÂ段ä¼Â被èªå¨åÂÂ建
è¿Âæ¯GORMçÂÂé»Â认æºå¶ï¼Â为äºÂèªå¨维æ¤æÂÂäºÂç¹æ®ÂÃ¥ÂÂ段çÂÂå¼ãÂÂ
ç¨éÂÂå®ÂÃ¥ÂÂ段çÂÂæÂ¥åÂÂ建
user := User{Name: "samuelZhang1", Age: 20}
db.Select("Name", "Age").Create(&user)
// INSERT INTO `users` (`created_at`,`updated_at`,`name`,`age`) VALUES ('2023-08-12 20:09:37.705','2023-08-12 20:09:37.705','samuelZhang1',20)
Ã¥ÂÂ建æ¶æÂÂé¤éÂÂå®ÂÃ¥ÂÂ段
user := User{Name: "samuelZhang2", Age: 20}
db.Omit("Age").Create(&user)
// INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ('2023-08-12 20:10:50.244','2023-08-12 20:10:50.244',NULL,'samuelZhang2')
è¦Â注æÂÂï¼ÂæÂÂé¤éÂÂå®ÂçÂÂÃ¥ÂÂ段éÂÂè¦Â注æÂÂå¯以为NULL
2.4 Read
2.4.1 主é®æ£Âç´¢
GORM æÂÂä¾Â亠First
ãÂÂLast
æ¹æ³Âï¼Â以便ä»Âæ°æ®åºÂä¸Âæ£Âç´¢åÂÂ个对象ãÂÂå½Âæ¥询æ°æ®åºÂæ¶å®Âæ·»å 亠LIMIT 1
æ¡件ï¼Âä¸Â没æÂÂæ¾å°记å½Âæ¶ï¼Âå®Âä¼Âè¿Âå ErrRecordNotFound
éÂÂ误
// æ ¹æ®主é®è·åÂÂ第ä¸Âæ¡记å½Âï¼Â主é®åÂÂåºÂï¼Â
user:=User{}
db.First(&userï¼Â1)
// SELECT * FROM users ORDER BY id LIMIT 1;
// æ ¹æ®主é®è·åÂÂæÂÂÃ¥ÂÂä¸Âæ¡记å½Âï¼Â主é®éÂÂåºÂï¼Â
user:=User{}
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
user:=User{}
result := db.First(&user)
println(result.RowsAffected) // è¿ÂÃ¥ÂÂæ¾å°çÂÂè®°å½Âæ°
println(result.Error) // returns error
// æ£ÂæÂÂ¥ ErrRecordNotFound éÂÂ误
errors.Is(result.Error, gorm.ErrRecordNotFound)
2.4.2 æ¡件æ£Âç´¢
String æ¡件
// è·åÂÂ第ä¸Âæ¡å¹éÂ
ÂçÂÂè®°å½Â
db.Where("name = ?", "Alex").First(&user)
// SELECT * FROM users WHERE name = 'Alex' ORDER BY id LIMIT 1;
// IN
db.Where("name IN ?", []string{"Alex", "Samuel"}).Find(&users)
// SELECT * FROM users WHERE name IN ('Alex','Samuel');
// LIKE
db.Where("name LIKE ?", "%lex%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%lex%';
// AND
db.Where("name = ? AND age >= ?", "Alex", "22").Find(&users)
// SELECT * FROM users WHERE name = 'Alex' 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';
注æÂÂï¼Â
- 使ç¨
First
Ã¥ÂÂLast
æ¥询åÂÂæ¡æ°æ®æ¶ï¼Âå¦ÂæÂÂæ¥询ä¸Âå°ï¼Âå®Âä¼Âè¿ÂÃ¥ÂÂErrRecordNotFound
éÂÂ误 - 使ç¨
Find
æ¥询å¤Âæ¡æ°æ®æ¶ï¼Âå¦ÂæÂÂæ¥询ä¸Âå°ï¼Âå®Âä¸Âä¼Âè¿ÂÃ¥ÂÂæ°æ®
Struct & Map æ¡件
// Struct
db.Where(&User{Name: "Alex", Age: 20}).First(&user)
// SELECT * FROM users WHERE name = "Alex" AND age = 20 ORDER BY id LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "Alex", "age": 20}).Find(&users)
// SELECT * FROM users WHERE name = "Alex" 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: "Alex", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "Alex";
æ¨å¯以使ç¨ map æÂ¥æÂÂ建æ¥询æ¡件ï¼Âä¾Âå¦Âï¼Â
db.Where(map[string]interface{}{"Name": "Alex", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "Alex" AND age = 0;
2.4.3 éÂÂæ©ç¹å®ÂÃ¥ÂÂ段
éÂÂæ©æ¨æ³ä»Âæ°æ®åºÂä¸Âæ£Âç´¢çÂÂÃ¥ÂÂ段ï¼Âé»Â认æ åµä¸Âä¼ÂéÂÂæ©堨é¨åÂÂ段
users := make([]User, 10)
db.Select("name", "age").Where("age > ?", 10).Find(&users)
// SELECT `name`,`age` FROM `users` WHERE age > 10 AND `users`.`deleted_at` IS NULL
db.Select([]string{"name", "age"}).Find(&users)
// SELECT `name`,`age` FROM `users` WHERE age > 10 AND `users`.`deleted_at` IS NULL
2.4.4 æºè½éÂÂæ©åÂÂ段
GORM Ã¥Â
Â许éÂÂè¿ Select
æ¹æ³ÂéÂÂæ©ç¹å®ÂçÂÂÃ¥ÂÂ段ï¼Âå¦ÂæÂÂæ¨å¨åºÂç¨ç¨ÂåºÂä¸Âç»Â常使ç¨æ¤åÂÂè½ï¼Âä½ ä¹Âå¯以å®Âä¹Âä¸Â个è¾Âå°ÂçÂÂç»ÂæÂÂä½Âï¼Â以å®Âç°è°Âç¨ API æ¶èªå¨éÂÂæ©ç¹å®ÂçÂÂÃ¥ÂÂ段ï¼Âä¾Âå¦Âï¼Â
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
2.5 Update
2.5.1 æ´æ°åÂÂ个åÂÂ
å½Â使ç¨ Update
æ´æ°åÂÂ个åÂÂæ¶ï¼Âä½ éÂÂè¦ÂæÂÂå®Âæ¡件ï¼Âå¦åÂÂä¼Âè¿Âå ErrMissingWhereClause
éÂÂ误ï¼ÂæÂ¥ç Block Global Updates è·åÂÂ详æÂÂ
ãÂÂå½Â使ç¨亠Model
æ¹æ³Âï¼Âä¸Â该对象主é®æÂÂå¼ï¼Â该å¼ä¼Â被ç¨äºÂæÂÂ建æ¡件ï¼Âä¾Âå¦Âï¼Â
// æ¡件æ´æ°
db.Model(&User{}).Where("id = ?", 1).Update("name", "hello")
// UPDATE `users` SET `name`='hello',`updated_at`='2023-08-12 19:38:13.34' WHERE id = 1 AND `users`.`deleted_at` IS NULL
user := User{}
user.ID=1
db.Model(&user).Update("name", "hello")
// UPDATE `users` SET `name`='hello',`updated_at`='2023-08-12 19:38:13.50' WHERE id = 1 AND `users`.`deleted_at` IS NULL
// æ ¹æ®æ¡件å model çÂÂå¼è¿Âè¡Âæ´æ°
user := User{}
user.ID=1
db.Model(&user).Where("age > ?",10 ).Update("name", "hello")
// UPDATE `users` SET `name`='hello',`updated_at`='2023-08-12 19:41:08.037' WHERE age > 10 AND `users`.`deleted_at` IS NULL AND `id` = 1
2.5.2 æ´æ°å¤ÂÃ¥ÂÂ
Updates
æ¹æ³Âæ¯æ struct
å map[string]interface{}
Ã¥ÂÂæ°ãÂÂå½Â使ç¨ struct
æ´æ°æ¶ï¼Âé»Â认æÂÂ
åµä¸Âï¼ÂGORM åªä¼Âæ´æ°éÂÂé¶å¼çÂÂÃ¥ÂÂ段ãÂÂ
// æ ¹æ® `struct` æ´æ°å±Âæ§ï¼Âåªä¼Âæ´æ°éÂÂé¶å¼çÂÂÃ¥ÂÂ段
user := User{}
user.ID = 1
db.Model(&user).Updates(User{Name: "hello", Age: 0}) // Ageå°Âä¼Â被忽çÂÂ¥
// UPDATE `users` SET `updated_at`='2023-08-12 19:45:15.084',`name`='hello' WHERE `users`.`deleted_at` IS NULL AND `id` = 1
// æ ¹æ® `map` æ´æ°å±Âæ§
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 0})
user := User{}
user.ID = 1
// UPDATE `users` SET `age`=0,`name`='hello',`updated_at`='2023-08-12 20:00:13.544' WHERE `users`.`deleted_at` IS NULL AND `id` = 1
注æ å½ÂéÂÂè¿ struct æ´æ°æ¶ï¼ÂGORM åªä¼Âæ´æ°éÂÂé¶åÂÂ段ã å¦ÂæÂÂæ¨æ³确ä¿ÂæÂÂå®ÂÃ¥ÂÂ段被æ´æ°ï¼Âä½ åºÂ该使ç¨
Select
æ´æ°éÂÂå®ÂÃ¥ÂÂ段ï¼ÂæÂÂ使ç¨map
æÂ¥å®ÂæÂÂæ´æ°æÂÂä½Â
2.5.3 æ´æ°éÂÂå®ÂÃ¥ÂÂ段
å¦ÂæÂÂæ¨æ³è¦Âå¨æ´æ°æ¶éÂÂå®ÂãÂÂ忽çÂ¥æÂÂäºÂÃ¥ÂÂ段ï¼Âæ¨å¯以使ç¨ Select
ãÂÂOmit
// Select å Map
user := User{}
user.ID = 1
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18}) // å°Âä¼Â忽çÂÂ¥age
// UPDATE `users` SET `name`='hello',`updated_at`='2023-08-12 20:04:43.168' WHERE `users`.`deleted_at` IS NULL AND `id` = 1
user := User{}
user.ID = 1
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 20})
// å°Âä¼Â忽çÂÂ¥name
// UPDATE `users` SET `age`=20,`updated_at`='2023-08-12 20:06:01.661' WHERE `users`.`deleted_at` IS NULL AND `id` = 1
// Select å Struct ï¼Âå¯以éÂÂä¸Âæ´æ°é¶å¼åÂÂ段ï¼Â
db.Model(&result).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})
// UPDATE `users` SET `updated_at`='2023-08-12 20:07:24.703',`name`='new_name',`age`=0 WHERE `users`.`deleted_at` IS NULL AND `id` = 1
2.5.4 æ¹éÂÂæ´æ°
å¦ÂæÂÂæ¨å°ÂæªéÂÂè¿ Model
æÂÂå®Âè®°å½ÂçÂÂ主é®ï¼Âå GORM ä¼Âæ§è¡Âæ¹éÂÂæ´æ°
// æ ¹æ® struct æ´æ°
db.Model(User{}).Where("age > ?", 30).Updates(User{Name: "hello", Age: 18})
// UPDATE `users` SET `updated_at`='2023-08-12 20:16:03.934',`name`='hello',`age`=18 WHERE age > 30 AND `users`.`deleted_at` IS NULL
// æ ¹æ® map æ´æ°
db.Table("users").Where("id IN ?", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 0})
// UPDATE `users` SET `age`=0,`name`='hello' WHERE id IN (10,11)
db.Tableç´æÂ¥æÂÂä½Âæ°æ®åºÂ表ï¼Â
- ä¸Âä¼Â触åÂÂ模åÂÂÃ¥ÂÂè°Âå½æ°
- ä¸Âä¼Âèªå¨æ´æ°æ¶é´æ³åÂÂ段
db.ModelæÂÂä½Â模åÂÂï¼Â
- ä¼Â触åÂÂÃ¥ÂÂè°Âå½æ°before/after update
- ä¼Âèªå¨æ´æ°æ¶é´æ³åÂÂ段
æÂÂ以使ç¨db.Tableè¿Âè¡Âæ´æ°æ¶ï¼Âä¸Âä¼Â触åÂÂUpdatedAtçÂÂèªå¨æ´æ°ãÂÂ
2.5.5 éÂȾ¢堨å±Âæ´æ°
å¦ÂæÂÂå¨没æÂÂä»»ä½Âæ¡件çÂÂæÂÂ
åµä¸Âæ§è¡Âæ¹éÂÂæ´æ°ï¼Âé»Â认æÂÂ
åµä¸Âï¼ÂGORM ä¸Âä¼Âæ§è¡Â该æÂÂä½Âï¼Â并è¿Âå ErrMissingWhereClause
éÂÂ误
对æ¤ï¼Âä½ å¿Â
é¡»å ä¸ÂäºÂæ¡件ï¼ÂæÂÂèÂÂ
使ç¨åÂÂç SQLï¼ÂæÂÂèÂÂ
å¯ç¨ AllowGlobalUpdate
模å¼Âï¼Âä¾Âå¦Âï¼Â
db.Model(&User{}).Update("name", "Alex").Error // gorm.ErrMissingWhereClause
db.Model(&User{}).Where("1 = 1").Update("name", "Alex")
// UPDATE `users` SET `name`='Alex',`updated_at`='2023-08-12 20:20:54.925' WHERE 1 = 1 AND `users`.`deleted_at` IS NULL
// db.Exec("UPDATE users SET name = ?", "Alex")
// è°¨æÂ
Â使ç¨ï¼Âä¼Âå°ÂæÂÂæÂÂçÂÂnameé½设置为Alex
// UPDATE users SET name = "Alex"
dB.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&User{}).Update("name", "Alex")
// UPDATE `users` SET `name`='Alex',`updated_at`='2023-08-12 20:22:16.459' WHERE `users`.`deleted_at` IS NULL
2.5.6 使ç¨ SQL 表达å¼Âæ´æ°
GORM å Â许使ç¨ SQL 表达å¼Âæ´æ°åÂÂï¼Âä¾Âå¦Âï¼Â
user := User{}
db.Model(&user).Where("id in ?", []uint{1, 2, 3}).Update("age", gorm.Expr("age - ?", 1))
// UPDATE `users` SET `age`=age - 1,`updated_at`='2023-08-13 14:55:07.472' WHERE id in (1,2,3) AND `users`.`deleted_at` IS NULL
user := User{}
db.Model(&user).Where("id in ?", []uint{1, 2, 3}).
Updates(map[string]interface{}{
"age": gorm.Expr("age * ? + ?", 0, 0),
"name": gorm.Expr("concat(name,?)", "db"),
})
// UPDATE `users` SET `age`=age * 0 + 0,`name`=concat(name,'db'),`updated_at`='2023-08-13 15:00:36.567' WHERE id in (1,2,3) AND `users`.`deleted_at` IS NULL
2.5.7 æ´æ°çÂÂè®°å½Âæ°
è·åÂÂÃ¥ÂÂæ´æ°影åÂÂçÂÂè¡Âæ°
// éÂÂè¿ `RowsAffected` å¾Âå°æ´æ°çÂÂè®°å½Âæ°
result := db.Model(User{}).Where("age != ?", 0).Updates(User{Name: "hello", Age: 18})
// UPDATE `users` SET `updated_at`='2023-08-12 20:24:42.952',`name`='hello',`age`=18 WHERE age != 0 AND `users`.`deleted_at` IS NULL
println(result.RowsAffected) // æ´æ°çÂÂè®°å½Âæ°
println(result.Error) // æ´æ°çÂÂéÂÂ误
2.6 Delete
2.6.1 ç©çÂÂå é¤
å é¤ä¸Âæ¡记å½Âæ¶ï¼Âå é¤对象éÂÂè¦ÂæÂÂå®Â主é®ï¼Âå¦åÂÂä¼Â触å æ¹é Deleteï¼Âä¾Âå¦Âï¼Â
// User表ç»ÂæÂÂ
type User struct {
Name string
Age int
}
// æ ¹æ®æ´形主é®çÂÂå é¤
db.Delete(&User{}, 10)
// DELETE from `users` where `users`.`id` = 10;
// æ ¹æ®é¢Âå¤Âæ¡件çÂÂå é¤ (ä¸Âé¢çÂÂä¾ÂÃ¥ÂÂå°Âä¼Âæ¹éÂÂå é¤)
db.Where("name = ?", "Alex").Delete(&User{},[]int{1,2,3})
// DELETE from `users`WHERE name = 'Alex' AND `users`.`id` IN (1,2,3);
2.6.2 软å é¤
å¦ÂæÂÂæ¨çÂÂ模åÂÂÃ¥ÂÂ
å«äºÂä¸Â个 gorm.deletedat
Ã¥ÂÂ段ï¼Âgorm.Model
å·²ç»ÂÃ¥ÂÂ
å«äºÂ该åÂÂ段)ï¼Âå®Âå°Âèªå¨è·å¾Â软å é¤çÂÂè½åÂÂï¼Â
æÂ¥æÂÂ软å é¤è½åÂÂçÂÂ模åÂÂè°Âç¨ Delete
æ¶ï¼Âè®°å½Âä¸Âä¼Â被ä»Âæ°æ®åºÂä¸ÂçÂÂæ£å é¤ãÂÂä½ GORM ä¼Âå° DeletedAt
置为å½ÂÃ¥ÂÂæ¶é´@并ä¸Âä½ ä¸Âè½åÂÂéÂÂè¿Âæ£常çÂÂæ¥询æ¹æ³Âæ¾å°该记å½ÂãÂÂ
// User表ç»ÂæÂÂ
type User struct {
gorm.Model
Name string
Age int
}
// æ ¹æ®æ´形主é®çÂÂå é¤
db.Delete(&User{}, 10)
// UPDATE `users` SET `deleted_at`='2023-08-13 15:04:13.696' WHERE `users`.`id` = 10 AND `users`.`deleted_at` IS NULL
// æ ¹æ®é¢Âå¤Âæ¡件çÂÂå é¤ (ä¸Âé¢çÂÂä¾ÂÃ¥ÂÂå°Âä¼Âæ¹éÂÂå é¤)
db.Where("name = ?", "Alex").Delete(&User{},[]int{1,2,3})
// UPDATE `users` SET `deleted_at`='2023-08-13 15:07:52.874' WHERE name = 'Alex' AND `users`.`id` IN (1,2,3) AND `users`.`deleted_at` IS NULL
æÂ¥æ¾被软å é¤çÂÂè®°å½Â
æ¨å¯以使ç¨ Unscoped
æ¾å°被软å é¤çÂÂè®°å½Â
users := make([]User, 10)
db.Unscoped().Where("name = ?", "Alex").Find(&users)
// SELECT * FROM `users` WHERE name = 'Alex'
永习å é¤
æ¨ä¹Âå¯以使ç¨ Unscoped
æ°¸ä¹Â
å é¤å¹éÂ
ÂçÂÂè®°å½Â
db.Unscoped().Where("name = ?", "Alex").Delete(&User{})
// DELETE FROM `users` WHERE name = 'Alex'
ä¸Âã æ»ç»Â
- 导堥GORMæ ¸å¿Âå ï¼Â以åÂÂå ·ä½Âæ°æ®åºÂçÂÂ驱å¨åÂÂ
- 使ç¨
db.Select
Ã¥ÂÂdb.Omit
æÂ¥éÂÂæ©åÂÂæÂÂé¤åÂÂ段ï¼Âè¦Â注æÂÂÃ¥ÂÂ段æ¯å¦å Â许为NULL
- æ¥询æÂÂæ´æ°é¶å¼ï¼Â
0
ãÂÂ''
ãÂÂfalse
ï¼Âï¼Â请使ç¨Where|Update(map[string]interface{}{"age":0})
æÂÂWhere|Update("age = 0")
æÂÂ建æ¥询æ¡件 - Ã¥ÂÂ建使ç¨
db.Create
- å¤Âæ¡æ°æ®使ç¨åÂÂçÂÂ
- è¿ÂÃ¥ÂÂæ°å¢Â主é®ãÂÂå½±åÂÂè¡Âæ°åÂÂå¼Â常
- æÂ¥æ¾使ç¨
db.Find
- éÂÂè¿Â
Where
ãÂÂOr
æ¡件è¯Âå¥æÂÂ建æ¥询æ¡件 - Ã¥ÂÂæ¡è¯Âå¥æÂÂå¨使ç¨
limit
è¿Âè¡ÂéÂÂå¶ - è¿ÂÃ¥ÂÂæÂ¥æ¾è¡Âæ°åÂÂå¼Â常
- éÂÂè¿Â
- æ´æ°使ç¨
db.Update
- Ã¥ÂÂÃ¥ÂÂ使ç¨
db.Model(User{}).Update
- å¤Â累使ç¨
db.Model(User{}).Updates
- ä¹Âå¯以使ç¨SQL表达å¼Âä½Â为æ´æ°çÂÂå¼
db.Model(User{}).Update("age", gorm.Expr("age - ?", 1))
- è¿ÂÃ¥ÂÂæ´æ°è¡Âæ°åÂÂå¼Â常
- Ã¥ÂÂÃ¥ÂÂ使ç¨
- å é¤使ç¨
db.Delete
- å¦ÂæÂÂModelä¸Âä¸ÂÃ¥ÂÂ
å«
gorm.deletedat
Ã¥ÂÂ段ï¼ÂÃ¥ÂÂä¼Âè¿Âè¡Âç©çÂÂå é¤ - å¦ÂæÂÂModelä¸ÂÃ¥ÂÂ
å«
gorm.deletedat
Ã¥ÂÂ段ï¼ÂÃ¥ÂÂä¼Âè¿Âè¡Âé»è¾Âå é¤ï¼Âå³软å é¤- 使ç¨
db.Unscoped()
ï¼ÂæÂ¥æ¾被æ Â记为软å é¤çÂÂè®°å½ - 使ç¨
db.Unscoped().Delete
ï¼Â对软å é¤çÂÂè®°å½Âè¿Âè¡Âç©çÂÂå é¤ - è¿ÂÃ¥ÂÂå é¤è¡Âæ°åÂÂå¼Â常
- 使ç¨
- å¦ÂæÂÂModelä¸Âä¸ÂÃ¥ÂÂ
å«