教程 > gorm 教程 > 阅读:308

gorm session——迹忆客-ag捕鱼王app官网

gorm 提供了 session 方法,这是一个 new session method,它允许创建带配置的新建会话模式:

// session 配置
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

生成 sql 但不执行。 它可以用于准备或测试生成的 sql,例如:

// 新建会话模式
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 模式
db, err := gorm.open(sqlite.open("gorm.db"), &gorm.config{dryrun: true})
// 不同的数据库生成不同的 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}

你可以使用下面的代码生成最终的 sql:

// 注意:sql 并不总是能安全地执行,gorm 仅将其用于日志,它可能导致会 sql 注入
db.dialector.explain(stmt.sql.string(), stmt.vars...)
// select * from `users` where `id` = 1

预编译

preparedstmt 在执行任何 sql 时都会创建一个 prepared statement 并将其缓存,以提高后续的效率,例如:

// 全局模式,所有 db 操作都会创建并缓存预编译语句
db, err := gorm.open(sqlite.open("gorm.db"), &gorm.config{
  preparestmt: true,
})
// 会话模式
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)
// 关闭 *当前会话* 的预编译模式
stmtmanger.close()
// 为 *当前会话* 预编译 sql
stmtmanger.preparedsql // => []string{}
// 为当前数据库连接池的(所有会话)开启预编译模式
stmtmanger.stmts // map[string]*sql.stmt
for sql, stmt := range stmtmanger.stmts {
  sql  // 预编译 sql
  stmt // 预编译模式
  stmt.close() // 关闭预编译模式
}

newdb

通过 newdb 选项创建一个不带之前条件的新 db,例如:

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` 选项
tx2 := db.where("name = ?", "jinzhu").session(&gorm.session{})
tx2.first(&user)
// select * from users where name = "jinzhu" order by id

初始化

创建一个新的初始化 db,它不再是 method chain/goroutine safe。

tx := db.session(&gorm.session{initialized: true})

跳过钩子

如果想跳过 hook 方法,可以使用 skiphooks 会话模式,例如:

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)

禁用嵌套事务

在一个 db 事务中使用 transaction 方法,gorm 会使用 savepoint(savedpointname)rollbackto(savedpointname) 为我们提供嵌套事务支持。 你可以通过 disablenestedtransaction 选项关闭它,例如:

db.session(&gorm.session{
  disablenestedtransaction: true,
}).createinbatches(&users, 100)
allowglobalupdate
gorm 默认不允许进行全局 update/delete,该操作会返回 errmissingwhereclause 错误。 您可以通过将一个选项设置为 true 来启用它,例如:
db.session(&gorm.session{
  allowglobalupdate: true,
}).model(&user{}).update("name", "jinzhu")
// update users set `name` = "jinzhu"

fullsaveassociations

在创建、更新记录时,gorm 会通过 upsert 自动保存关联及其引用记录。 如果我们想要更新关联的数据,应该使用 fullsaveassociations 模式,例如:

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

通过 context 选项,我们可以传入 context 来追踪 sql 操作,例如:

timeoutctx, _ := context.withtimeout(context.background(), time.second)
tx := db.session(&session{context: timeoutctx})
tx.first(&user) // 带有 context timeoutctx 的查询操作
tx.model(&user).update("role", "admin") // 带有 context timeoutctx 的更新操作

gorm 也提供了简写形式的方法 withcontext,其实现如下:

func (db *db) withcontext(ctx context.context) *db {
  return db.session(&session{context: ctx})
}

自定义 logger

gorm 允许使用 logger 选项自定义内建 logger,例如:

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)})

查看 logger 获取更多信息。


nowfunc

nowfunc 允许改变 gorm 获取当前时间的实现,例如:

db.session(&session{
  nowfunc: func() time.time {
    return time.now().local()
  },
})

调试

debug 只是将会话的 logger 修改为调试模式的简写形式,其实现如下:

func (db *db) debug() (tx *db) {
  return db.session(&session{
    logger:         db.logger.logmode(logger.info),
  })
}

查询字段

声明查询字段

db.session(&gorm.session{queryfields: true}).find(&user)
// select `users`.`name`, `users`.`age`, ... from `users` // 有该选项
// select * from `users` // 没有该选项

createbatchsize

默认批量大小

users = [5000]user{{name: "jinzhu", pets: []pet{pet1, pet2, pet3}}...}
db.session(&gorm.session{createbatchsize: 1000}).create(&users)
// insert into users xxx (需 5 次)
// insert into pets xxx (需 15 次)

查看笔记

扫码一下
查看教程更方便
网站地图