golang ORM框架gorm

本文详细介绍了GORM,一个流行的Go语言ORM框架,包括安装、快速入门、模型定义、数据库连接、会话、操作、关联关系、事务等内容。GORM支持MySQL、PostgreSQL、SQLite等多种数据库,提供了字段级权限控制、嵌入结构体、自动追踪创建/更新时间等功能,并允许通过标签定制字段。文章还涵盖了如何进行预加载、创建、查询、更新和删除记录,以及如何处理多对一、一对多、多对多关系。此外,还讲解了事务的使用和嵌套事务的处理方式。
摘要由CSDN通过智能技术生成

ORM简介

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库(如mysql数据库)存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。

安装

go get -u gorm.io/gorm

快速入门

安装驱动

go get -u gorm.io/gorm
go get -u github.com/go-sql-driver/mysql
package main

import (
  "gorm.io/gorm"
  "gorm.io/driver/mysql"
)

type Product struct {
   
  gorm.Model
  Code  string
  Price uint
}

func main() {
   
  dsn := "username:password@tcp(ip:port)/database?charset=utf8mb4&parseTime=True&loc=Local"
  if err != nil {
   
    panic("failed to connect database")
  }

  // 迁移 schema
  db.AutoMigrate(&Product{
   })

  // Create
  db.Create(&Product{
   Code: "D42", Price: 100})

  // Read
  var product Product
  db.First(&product, 1) // 根据整形主键查找
  db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录

  // Update - 将 product 的 price 更新为 200
  db.Model(&product).Update("Price", 200)
  // Update - 更新多个字段
  db.Model(&product).Updates(Product{
   Price: 200, Code: "F42"}) // 仅更新非零值字段
  db.Model(&product).Updates(map[string]interface{
   }{
   "Price": 200, "Code": "F42"})

  // Delete - 删除 product
  db.Delete(&product, 1)
}

模型定义

模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成
GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间
遵循 GORM 已有的约定,可以减少您的配置和代码量。如果约定不符合您的需求,GORM 允许您自定义配置它们

gorm.Model

GORM 定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt

// gorm.Model 的定义
type Model struct {
   
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

您可以将它嵌入到您的结构体中,以包含这几个字段

高级选项

字段级权限控制

可导出的字段在使用 GORM 进行 CRUD 时拥有全部的权限,此外,GORM 允许您用标签控制字段级别的权限。这样您就可以让一个字段的权限是只读、只写、只创建、只更新或者被忽略

注意: 使用 GORM Migrator 创建表时,不会创建被忽略的字段

type User struct {
   
  Name string `gorm:"<-:create"` // 允许读和创建
  Name string `gorm:"<-:update"` // 允许读和更新
  Name string `gorm:"<-"`        // 允许读和写(创建和更新)
  Name string `gorm:"<-:false"`  // 允许读,禁止写
  Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)
  Name string `gorm:"->;<-:create"` // 允许读和写
  Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
  Name string `gorm:"-"`  // 通过 struct 读写会忽略该字段
}

创建/更新时间追踪(纳秒、毫秒、秒、Time)
GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间

要使用不同名称的字段,您可以配置 autoCreateTime、autoUpdateTime 标签

如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可

type User struct {
   
  CreatedAt time.Time // Set to current time if it is zero on creating
  UpdatedAt int       // Set to current unix seconds on updating or if it is zero on creating
  Updated   int64 `gorm:"autoUpdateTime:nano"` // Use unix nano seconds as updating time
  Updated   int64 `gorm:"autoUpdateTime:milli"`// Use unix milli seconds as updating time
  Created   int64 `gorm:"autoCreateTime"`      // Use unix seconds as creating time
}

嵌入结构体

对于匿名字段,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
}

并且,您可以使用标签 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
}

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase 风格

标签名 说明
column 指定 db 列名
type 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not null、size, autoIncrement… 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT
size 指定列大小,例如:size:256
primaryKey 指定列为主键
unique 指定列为唯一
default 指定列的默认值
precision 指定列的精度
scale 指定列大小
not null 指定列为 NOT NULL
autoIncrement 指定列为自动增长
autoIncrementIncrement 自动步长,控制连续记录之间的间隔
embedded 嵌套字段
embeddedPrefix 嵌入字段的列名前缀
autoCreateTime 创建时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano
autoUpdateTime 创建/更新时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli
index 根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情
uniqueIndex 与 index 相同,但创建的是唯一索引
check 创建检查约束,例如 check:age > 13,查看 约束 获取详情
<- 设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限
-> 设置字段读的权限,->:false 无读权限
- 忽略该字段,- 无读写权限
comment 迁移时为字段添加注释

关联标签

GORM 允许通过标签为关联配置外键、约束、many2many 表

gorm连接到数据库

GORM 官方支持的数据库类型有:MySQL, PostgreSQL, SQlite, SQL Server

MySQL

import (
 "gorm.io/driver/mysql"
 "gorm.io/gorm"
)

func main() {
   
 // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
 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{
   })
}

注意:想要正确的处理 time.Time ,您需要带上 parseTime 参数, (更多参数) 要支持完整的 UTF-8 编码,您需要将
charset=utf8 更改为 charset=utf8mb4

MySQl 驱动程序提供了 一些高级配置 可以在初始化过程中使用,例如:

db, err := gorm.Open(mysql.New(mysql.Config{
   
 DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
 DefaultStringSize: 256, // string 类型字段的默认长度
 DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
 DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
 DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
 SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{
   })

自定义驱动
GORM 允许通过 DriverName 选项自定义 MySQL 驱动,例如:

import (
 _ "example.com/my_mysql_driver"
 "gorm.io/gorm"
)

db, err := gorm.Open(mysql.New(mysql.Config{
   
 DriverName: "my_mysql_driver",
 DSN: "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local", // Data Source Name,参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name
}), &gorm.Config{
   })

现有的数据库连接
GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB

import (
 "database/sql"
 "gorm.io/gorm"
)

sqlDB, err := sql.Open("mysql", "mydb_dsn")
gormDB, err := gorm.Open(mysql.New(mysql.Config{
   
 Conn: sqlDB,
}), &gorm.Config{
   })

PostgreSQL

import (
 "gorm.io/driver/postgres"
 "gorm.io/gorm"
)

dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
   })

我们使用 pgx 作为 postgres 的 database/sql 驱动,默认情况下,它会启用 prepared statement 缓存,你可以这样禁用它:

// https://github.com/go-gorm/postgres
db, err := gorm.Open(postgres.New(postgres.Config{
   
 DSN: "user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai",
 PreferSimpleProtocol: true, // disables implicit prepared statement usage
}), &gorm.Config{
   })

自定义驱动
GORM 允许通过 DriverName 选项自定义 PostgreSQL 驱动,例如:

import (
 _ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
 "gorm.io/gorm"
)

db, err := gorm.Open(postgres.New(postgres.Config{
   
 DriverName: "cloudsqlpostgres",
 DSN: "host=project:region:instance user=postgres dbname=postgres password=password sslmode=disable",
})

现有的数据库连接
GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB

import (
 "database/sql"
 "gorm.io/gorm"
)

sqlDB, err := sql.Open("postgres", "mydb_dsn")
gormDB, err := gorm.Open(postgres.New(postgres.Config{
   
 Conn: sqlDB,
}), &gorm.Config{
   })

SQLite

import (
 "gorm.io/driver/sqlite"
 "gorm.io/gorm"
)

// github.com/mattn/go-sqlite3
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
   })

注意: 您也可以使用 file::memory:?cache=shared 替代文件路径。这会告诉 SQLite在系统内存中使用一个临时数据库。

SQL Server

import (
 "gorm.io/driver/sqlserver"
 "gorm.io/gorm"
)

// github.com/denisenkom/go-mssqldb
dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{
   })

Clickhouse

https://github.com/go-gorm/clickhouse

import (
 "gorm.io/driver/clickhouse"
 "gorm.io/gorm"
)

func main() {
   
 dsn := "tcp://localhost:9000?database=gorm&username=gorm&password=gorm&read_timeout=10&write_timeout=20"
 db, err := gorm.Open(clickhouse.Open(dsn), &gorm.Config{
   })

 // Auto Migrate
 db.AutoMigrate(&User{
   })
 // Set table options
 db.Set("gorm:table_options", "ENGINE=Distributed(cluster, default, hits)").AutoMigrate(&User{
   })

 // 插入
 db.Create(&user)

 // 查询
 db.Find(&user, "id = ?", 10)

 // 批量插入
 var users = []User{
   user1, user2, user3}
 db.Create(&users)
 // ...
}

连接池

GORM 使用 database/sql 维护连接池

sqlDB, err := db.DB()

// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)

gorm 会话

GORM 提供了 Session 方法,这是一个 New Session Method,它允许创建带配置的新建会话模式:

// Session 配置
type Session struct {
   
 DryRun                 bool
 PrepareStmt            bool
 NewDB                  bool
 SkipHooks              bool
 SkipDefaultTransaction bool
 AllowGlobalUpdate      bool
 FullSaveAssociations   bool
 Context                context.Context
 Logger                 logger.Interface
 NowFunc                func() time.Time
}

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

跳过钩子
如果您想跳过 钩子 方法,您可以使用 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) // 带 timeoutCtx 的查询
tx.Model(&user).Update("role", "admin") // 带 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)})

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

db.Session(&Session{
   
 NowFunc: func() time.Time {
   
   return time.Now().Local()
},
})

Debug
Debug 只是将会话的 Logger 修改为调试模式的快捷方法,其实现如下:

func (db *DB) Debug() (tx *DB) {
   
 return db.Session(&Session{
   
   Logger:         db.Logger.LogMode(logger.Info),
})
}

QueryFields
select by fields

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

gorm操作

gorm原生SQL和SQL 构建器

原生 SQL
原生查询 SQL 和 Scan

type Result struct {
   
 ID   int
 Name string
 Age  int
}
var result Result
db.Raw("SELECT id, name, age FROM users WHERE name = ?", 3).Scan(&result)

db.Raw("SELECT id, name, age FROM users WHERE name = ?", 3).Scan(&result)

var age int
db.Raw("SELECT SUM(age) FROM users WHERE role = ?", "admin").Scan(&age)

var users []User
db.Raw("UPDATE users SET name = ? WHERE age = ? RETURNING id, name", "jinzhu", 20).Scan(&users)

Exec 原生 SQL

db.Exec("DROP TABLE users")
db.Exec("UPDATE orders SET shipped_at = ? WHERE id IN ?", time.Now(), []int64{
   1, 2, 3})

// Exec with SQL Expression
db.Exec("UPDATE users SET money = ? WHERE name = ?", gorm.Expr("money * ? + ?", 10000, 1), "jinzhu")

注意 GORM 允许缓存预编译 SQL 语句来提高性能

命名参数
GORM 支持 sql.NamedArg、map[string]interface{}{} 或 struct 形式的命名参数,例如:

db.Where("name1 = @name OR name2 = @name", sql.Named("name", "jinzhu")).Find(&user)
// SELECT * FROM `users` WHERE name1 = "jinzhu" OR name2 = "jinzhu"

db.Where("name1 = @name OR name2 = @name", map[string]interface{
   }{
   "name": "jinzhu2"}).First(&result3)
// SELECT * FROM `users` WHERE name1 = "jinzhu2" OR name2 = "jinzhu2" ORDER BY `users`.`id` LIMIT 1

// 原生 SQL 及命名参数
db.Raw("SELECT * FROM users WHERE name1 = @name OR name2 = @name2 OR name3 = @name",
  sql.Named("name", "jinzhu1"), sql.Named("name2", "jinzhu2")).Find(&user)
// SELECT * FROM users WHERE name1 = "jinzhu1" OR name2 = "jinzhu2" OR name3 = "jinzhu1"

db.Exec("UPDATE users SET name1 = @name, name2 = @name2, name3 = @name",
  sql.Named("name", "jinzhunew"), sql.Named("name2", "jinzhunew2"))
// UPDATE users SET name1 = "jinzhunew", name2 = "jinzhunew2", name3 = "jinzhunew"

db.Raw("SELECT * FROM users WHERE (name1 = @name AND name3 = @name) AND name2 = @name2",
  map[string]interface{
   }{
   "name": "jinzhu", "name2": "jinzhu2"}).Find(&user)
// SELECT * FROM users WHERE (name1 = "jinzhu" AND name3 = "jinzhu") AND name2 = "jinzhu2"

type NamedArgument struct {
   
   Name string
   Name2 string
}

db.Raw("SELECT * FROM users WHERE (name1 = @Name AND name3 = @Name) AND name2 = @Name2",
    NamedArgument{
   Name: "jinzhu", Name2: "jinzhu2"}).Find(&user)
// SELECT * FROM users WHERE (name1 = "jinzhu" AND name3 = "jinzhu") AND name2 = "jinzhu2"

DryRun 模式
GenerateSQL及其参数不执行,可用于准备或测试生成的 SQL,Checkout Session了解详情

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}

ToSQL
返回生成SQL而不执行。

GORM使用database/sql的参数占位符来构造SQL语句,会自动转义参数以避免SQL注入,但生成的SQL不提供安全保证,请仅用于调试。

sql := DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
   
 return tx.Model(&User{
   }).Where("id = ?", 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值