这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记。
database/sql
基本用法
建立 driver
//常规写法
db, err := sql.Open(
mysql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello")
)
//更好的写法,使用结构体
connector, err := mysqk.NewConnector(&mysql.Config{
User: "gorm",
Passwd: "gorm",
Net: "tcp",
Addr: "127.0.0.1:3306",
DBName: "gorm",
ParseTime: true,
})
db := sql.OpenDB(connector)
sql操作
rows, err := db.Query("select id, name from user where id = ?", 1)
//最后一定要close
defer func(){
err = rows.Close()
}
//使用 Next() 方法和 Scan() 方法来实现数据库的中数据的读取
var users []User
for rows.Next(){
var user User
err := rows.Scan(&user.ID, &user.Name)
users = append(users, user)
}
if rows.Err() != nil{
//
}
GORM
设计简洁、功能强大、自由拓展的全功能 ORM
基本用法
建立 driver
db, err := gorm.Open(
mysql.Open("user:password@tcp(127.0.0.1:3306)/hello")
)
select 操作
var user User
err = db.Select("id","name").Find(&users, 1).Error
模型定义
约定优于配置
下面是一些惯例约定:
- 表名是 stuct name 的复数格式
- 字段名是field name 的单数格式
- ID / Id 字段为主键,如果是数字,则为自增主键
- CreatedAt 字段,创建时保存当前时间
- UpdatedAt 字段,创建、更新时保存当前时间
- DeletedAt 字段,默认开启 soft delete 模式
设计原理
SELECT * FROM user WHERE role <> "manager" AND age > 35 ORDER BY age desc LIMIT 100
使用GORM可以代替为
db.Where("role <> ?", "manager").Where("age > ?", 35).Limit(100).Order("age desc").Find(&user)
GORM STATEMENT 由 GORM Clauses 和 Finisher Method来构成
其中 GORM Clauses 包括了多个 Chain Method
执行流程:Finisher Method => 决定 Statement 类型 => 执行 Callbacks => 生成 SQL 并执行
多租户
插件在工作时会强制根据TenantID来进行过滤
多数据库、读写分离
使用 Write 模式: 从 sources db 读取 指定 Resolver : 从 secondary 的 replicas db 中读取 指定 Resolver 和 Write 模式: 从 secondary 的 sources db 读取
ConnPool
一行代码提高SQL效率,关闭SQL预编译
interpolateParams=false
Dialector
GORM 实践
SQL表达式更新创建
-
通过
gorm.Expr来使用SQL表达式 -
使用
GORMValuer来使用SQL表达式 -
通过
*gorm.DB使用SubQuery
SQL表达式查询
-
使用
gorm.Expr -
Struct定义GORMValuer -
自定义查询SQL实现接口
clause.Expression -
使用
SubQuery
批量创建/查询
使用CreateInBatches()方法,以某个数量为单位进行分组创建
使用FindInBatches()方法,以某个数量为单位进行分组查找
批量数据加速操作
-
关闭默认事务
-
默认批量导入回调用 Hooks 方法,使用
Skiphooks跳过 -
使用 Prepared Statement
-
混合使用
Gen代码生成
//生成自定义SQL静态代码
g:=gen.NewGenerator(gen.Config{
OutPath: "../dal/query",
})
g.ApplyBasic(model.User{})//生成对应的CURD API
g.ApplyInterface(func(query method.Query) {}, model.User{})//给User生成Query Interface方法
g.Execute()
//查询
user, err := query.User.FindUser(10,"xxx", 16)
安全
拼接存在危险,会引起SQL注入,应以参数的形式传入