Session
原文:https://gorm.io/docs/session.html
GORM provides Session
method, which is a New Session Method
, it allows to create a new session mode with configuration:
GORM提供了一个Session
方法,它是一个新会话方法,允许使用配置创建一个新的会话模式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // Session Configuration
type Session struct {
DryRun bool
PrepareStmt bool
NewDB bool
Initialized bool
SkipHooks bool
SkipDefaultTransaction bool
DisableNestedTransaction bool
AllowGlobalUpdate bool
FullSaveAssociations bool
QueryFields bool
Context context.Context
Logger logger.Interface
NowFunc func() time.Time
CreateBatchSize int
}
|
DryRun
Generates SQL
without executing. It can be used to prepare or test generated SQL, for example:
生成SQL
而不执行。它可以用于准备或测试生成的SQL,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
| // 会话模式 session mode
stmt := db.Session(&Session{DryRun: true}).First(&user, 1).Statement
stmt.SQL.String() //=> SELECT * FROM `users` WHERE `id` = $1 ORDER BY `id`
stmt.Vars //=> []interface{}{1}
// 全局模式下的DryRun globally mode with DryRun
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{DryRun: true})
// 不同的数据库生成不同的SQL different databases generate different SQL
stmt := db.Find(&user, 1).Statement
stmt.SQL.String() //=> SELECT * FROM `users` WHERE `id` = $1 // PostgreSQL
stmt.SQL.String() //=> SELECT * FROM `users` WHERE `id` = ? // MySQL
stmt.Vars //=> []interface{}{1}
|
To generate the final SQL, you could use following code:
要生成最终的SQL,可以使用以下代码:
1
2
3
| // 注意:SQL并不总是安全的执行,GORM仅用于日志记录,它可能导致SQL注入 NOTE: the SQL is not always safe to execute, GORM only uses it for logs, it might cause SQL injection
db.Dialector.Explain(stmt.SQL.String(), stmt.Vars...)
// SELECT * FROM `users` WHERE `id` = 1
|
PrepareStmt
PreparedStmt
creates prepared statements when executing any SQL and caches them to speed up future calls, for example:
PreparedStmt
在执行任何SQL时创建预处理语句并缓存它们以加速未来的调用,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // 全局模式下,所有数据库操作将创建预处理语句并缓存它们 globally mode, all DB operations will create prepared statements and cache them
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
PrepareStmt: true,
})
// 会话模式 session mode
tx := db.Session(&Session{PrepareStmt: true})
tx.First(&user, 1)
tx.Find(&users)
tx.Model(&user).Update("Age", 18)
// 返回预处理语句管理器 returns prepared statements manager
stmtManger, ok := tx.ConnPool.(*PreparedStmtDB)
// 关闭当前会话的预处理语句 close prepared statements for *current session*
stmtManger.Close()
// 当前会话的预处理SQL prepared SQL for *current session*
stmtManger.PreparedSQL // => []string{}
// 当前数据库连接池(所有会话)的预处理语句 prepared statements for current database connection pool (all sessions)
stmtManger.Stmts // map[string]*sql.Stmt
for sql, stmt := range stmtManger.Stmts {
sql // 预处理SQL prepared SQL
stmt // 预处理语句 prepared statement
stmt.Close() // 关闭预处理语句 close the prepared statement
}
|
NewDB
Create a new DB without conditions with option NewDB
, for example:
创建一个没有条件的新DB,使用选项NewDB
,例如:
1
2
3
4
5
6
7
8
9
10
11
12
| tx := db.Where("name = ?", "jinzhu").Session(&gorm.Session{NewDB: true})
tx.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1
tx.First(&user, "id = ?", 10)
// SELECT * FROM users WHERE id = 10 ORDER BY id
// 不使用选项`NewDB` Without option `NewDB`
tx2 := db.Where("name = ?", "jinzhu").Session(&gorm.Session{})
tx2.First(&user)
// SELECT * FROM users WHERE name = "jinzhu" ORDER BY id
|
Initialized
Create a new initialized DB, which is not Method Chain/Goroutine Safe anymore, refer Method Chaining
创建一个初始化的DB,它不再是Method Chain/Goroutine Safe anymore,参考Method Chaining
1
| tx := db.Session(&gorm.Session{Initialized: true})
|
Skip Hooks
If you want to skip Hooks
methods, you can use the SkipHooks
session mode, for example:
如果你想要跳过Hooks
方法,你可以使用SkipHooks
会话模式,例如:
1
2
3
4
5
6
7
8
9
10
11
| DB.Session(&gorm.Session{SkipHooks: true}).Create(&user)
DB.Session(&gorm.Session{SkipHooks: true}).Create(&users)
DB.Session(&gorm.Session{SkipHooks: true}).CreateInBatches(users, 100)
DB.Session(&gorm.Session{SkipHooks: true}).Find(&user)
DB.Session(&gorm.Session{SkipHooks: true}).Delete(&user)
DB.Session(&gorm.Session{SkipHooks: true}).Model(User{}).Where("age > ?", 18).Updates(&user)
|
DisableNestedTransaction
When using Transaction
method inside a DB transaction, GORM will use SavePoint(savedPointName)
, RollbackTo(savedPointName)
to give you the nested transaction support. You can disable it by using the DisableNestedTransaction
option, for example:
当在DB事务内使用Transaction
方法时,GORM将使用SavePoint(savedPointName)
,RollbackTo(savedPointName)
来给你提供嵌套事务支持。你可以通过设置此选项为true来启用它,例如:
1
2
3
| db.Session(&gorm.Session{
DisableNestedTransaction: true,
}).CreateInBatches(&users, 100)
|
AllowGlobalUpdate
GORM doesn’t allow global update/delete by default, will return ErrMissingWhereClause
error. You can set this option to true to enable it, for example:
GORM默认不允许全局更新/删除,将返回ErrMissingWhereClause
错误。您可以将此选项设置为true以启用它,例如:
1
2
3
4
| db.Session(&gorm.Session{
AllowGlobalUpdate: true,
}).Model(&User{}).Update("name", "jinzhu")
// UPDATE users SET `name` = "jinzhu"
|
FullSaveAssociations
GORM will auto-save associations and its reference using Upsert when creating/updating a record. If you want to update associations’ data, you should use the FullSaveAssociations
mode, for example:
GORM在创建/更新记录时将自动使用Upsert保存关联及其引用。如果你想更新关联的数据,你应该使用FullSaveAssociations
模式,例如:
1
2
3
4
5
6
| db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)
// ...
// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1"), ("Shipping Address - Address 1") ON DUPLICATE KEY SET address1=VALUES(address1);
// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu@example.com"), (111, "jinzhu-2@example.com") ON DUPLICATE KEY SET email=VALUES(email);
// ...
|
Context
With the Context
option, you can set the Context
for following SQL operations, for example:
使用Context
选项,你可以为后续的SQL操作设置Context
,例如:
1
2
3
4
5
| timeoutCtx, _ := context.WithTimeout(context.Background(), time.Second)
tx := db.Session(&Session{Context: timeoutCtx})
tx.First(&user) // 使用timeoutCtx查询 query with context timeoutCtx
tx.Model(&user).Update("role", "admin") // 使用timeoutCtx更新 update with context timeoutCtx
|
GORM also provides shortcut method WithContext
, here is the definition:
GORM还提供了快捷方法WithContext
,这里是定义:
1
2
3
| func (db *DB) WithContext(ctx context.Context) *DB {
return db.Session(&Session{Context: ctx})
}
|
日志记录器 Logger
Gorm allows customizing built-in logger with the Logger
option, for example:
Gorm允许使用Logger
选项自定义内置日志记录器,例如:
1
2
3
4
5
6
7
8
9
| newLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Silent,
Colorful: false,
})
db.Session(&Session{Logger: newLogger})
db.Session(&Session{Logger: logger.Default.LogMode(logger.Silent)})
|
Checkout Logger for more details.
更多详细信息请查看日志记录器。
NowFunc
NowFunc
allows changing the function to get current time of GORM, for example:
NowFunc
允许更改获取GORM当前时间的函数,例如:
1
2
3
4
5
| db.Session(&Session{
NowFunc: func() time.Time {
return time.Now().Local()
},
})
|
调试 Debug
Debug
is a shortcut method to change session’s Logger
to debug mode, here is the definition:
Debug
是一个快捷方法,用于将会话的Logger
更改为调试模式,以下是定义:
1
2
3
4
5
| func (db *DB) Debug() (tx *DB) {
return db.Session(&Session{
Logger: db.Logger.LogMode(logger.Info),
})
}
|
QueryFields
Select by fields
按字段选择
1
2
3
| db.Session(&gorm.Session{QueryFields: true}).Find(&user)
// SELECT `users`.`name`, `users`.`age`, ... FROM `users` // with this option
// SELECT * FROM `users` // without this option
|
CreateBatchSize
Default batch size
默认批处理大小
1
2
3
4
5
| users = [5000]User{{Name: "jinzhu", Pets: []Pet{pet1, pet2, pet3}}...}
db.Session(&gorm.Session{CreateBatchSize: 1000}).Create(&users)
// INSERT INTO users xxx (5 batches)
// INSERT INTO pets xxx (15 batches)
|