一、前言
本篇文章主要为GORM实践的代码及注释。
二、实践
数据序列化与SQL表达式-SQL表达式更新创建
// 方法一:通过gorm.Expr使用SQL表达式
db.Model(User{}).Create(map[string]interface{}{
"Name":"jinzhu",
"Location":gorm.Expr("ST_PointFromText(?)","POINT(100 100)"),
})
db.Model(&product).Update("price",gorm.Expr("price * ? + ?, 2, 100))
// 方法2:使用GORMValuer使用SQL表达式 / SubQuery
type Location struct {
X, Y int
}
func (loc Location) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return gorm.Expr("ST_PointFromText(?)", fmt.Sprintf("POINT(%d %d)", loc.X, loc.Y))
db.Create(User{Name: "jinzhu", Location: Location{X: 100, Y:100}})
//方法3:通过 *gorm.DB 使用SubQuery
subQuery := db.Model(&Company{}).Select("name").Where("companies.id = users.company_id)
db.Model(&user).Updates(map[string]interface{}{}{"company_name": subQuery})
**批量数据操作-批量创建/查询
// 批量创建
var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.Create(&users)
db.CreateInBatches(users, 100)
for _, user := range users {
user.ID
}
// 批量查询
rows, err := db.Model(&User{}).Where("role = ?", "admin").Rows()
for rows.Next()
// 方法1:sql.Rows Scan
rows.Scan(&name, &age, &email)
// 方法2:gorm ScanRows
db.ScanRows(rows, &user)
}
DB.Where("role = ?", "admin").FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error{})
代码复用、分库分表、Sharding -代码复用
func Paginate(r *http.Request) func(db *gorm.DB) *gorm.DB {
return func (db *gorm.DB) *gorm.DB {
page, _ := strconv.Atoi(r.Query("page"))
if page ==0 {
page = 1
}
pageSize, _ :=strconv.Atoi(r.Query("page_size"))
switch {
case pageSize > 100:
pageSize = 100
case pageSize <= 0:
pageSize = 10
}
offset := (page - 1) * pageSize
return db.Offset(offset).Limit(pageSize)
}
}
// 代码共享
db.Scopes(Paginate(r)).Find(&users)
db.Scopes(Paginate(r)).Find(&articles)
混沌工程
import (
"example.com/gorm/sqlchaos"
"gorm.io/gorm"
)
db, err := gorm.Open(
mysql.Open(dsn),
&gorm.Config{},
sqlchaos.WithChaos(sqlchaos.Config{
PSM: "service name",
DBName: "dbname",
EnvList: []string{"ppe", "boe"},
}),
)
db.Create(&User{ID: 1024, Name: "rick", Result: 10})