2 Star 1 Fork 0

法马智慧/fmgo

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
query.go 3.70 KB
一键复制 编辑 原始数据 按行查看 历史
零海 提交于 2022-12-01 17:03 . gcache会二次查询会成为空值
package gcache
import (
"encoding/json"
"fmt"
"gorm.io/gorm"
"gorm.io/gorm/callbacks"
"reflect"
"strings"
"time"
)
type Model interface{}
type JsonSearch struct {
PrimaryKeys []string `json:"primary_keys"`
}
func (e *Engine) BeforeQuery(tx *gorm.DB) {
for _, clauses := range tx.Statement.BuildClauses {
if c, ok := tx.Statement.Clauses[clauses]; ok {
if b, ok := tx.Statement.ClauseBuilders[clauses]; ok {
b(c, tx.Statement)
} else {
c.Build(tx.Statement)
}
}
}
// Redis 获取数据
sqlStr := generateKey(tx.Statement.SQL.String())
vars := make([]string, 0)
for _, elem := range tx.Statement.Vars {
vars = append(vars, fmt.Sprintf("%v", elem))
}
paramStr := generateKey(strings.Join(vars, "_"))
tx.Statement.SQL = strings.Builder{}
tx.Statement.Vars = []interface{}{}
if tx.Statement.Joins != nil {
e.opt.Logger.Info("存在Join方法,跳过缓存")
return
}
searchKey := getSearchKey(tx.Statement.Table, sqlStr, paramStr)
tx.InstanceSet("gorm:cache:searchKey", searchKey)
e.opt.Logger.Info(searchKey)
// 获取主键信息
row, err := e.rdb.Get(tx.Statement.Context, searchKey).Result()
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
if row == "" {
tx.RowsAffected = -1
return
}
searchInfo := &JsonSearch{}
err = json.Unmarshal([]byte(row), searchInfo)
if err != nil {
return
}
modelKeys := make([]string, 0)
for _, primaryKey := range searchInfo.PrimaryKeys {
modelKeys = append(modelKeys, getModelKey(tx.Statement.Table, primaryKey))
}
models, err := e.rdb.MGet(tx.Statement.Context, modelKeys...).Result()
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
// 判断是否获取到所有数据
for _, model := range models {
if model == nil {
e.opt.Logger.Info("缓存数据不全,跳过缓存")
return
}
}
callbacks.BuildQuerySQL(tx)
var cacheValues []string
for _, model := range models {
cacheValues = append(cacheValues, model.(string))
}
finalValue := ""
destKind := reflect.Indirect(reflect.ValueOf(tx.Statement.Dest)).Kind()
if destKind == reflect.Struct && len(cacheValues) == 1 {
finalValue = cacheValues[0]
} else if (destKind == reflect.Array || destKind == reflect.Slice) && len(cacheValues) >= 1 {
finalValue = "[" + strings.Join(cacheValues, ",") + "]"
}
tx.Statement.RowsAffected = int64(len(cacheValues))
err = json.Unmarshal([]byte(finalValue), tx.Statement.Dest)
tx.Error = PrimaryCacheHit
e.opt.Logger.Info(fmt.Sprint(tx.Statement.Dest))
}
func (e *Engine) AfterQuery(tx *gorm.DB) {
if tx.Error == PrimaryCacheHit {
tx.Error = nil
e.opt.Logger.Info("命中缓存:", tx.Statement.Table)
return
}
// Redis 获取数据
hsetKeyObj, ok := tx.InstanceGet("gorm:cache:searchKey")
if !ok {
return
}
hsetKey := hsetKeyObj.(string)
// 写入缓存
primaryKeys, objectMap := getObjectsAfterLoad(tx)
e.opt.Logger.Info(fmt.Sprint(primaryKeys))
e.opt.Logger.Info(fmt.Sprint(objectMap))
//tx.ScanRows()
pipeline := e.rdb.Pipeline()
searchModel := JsonSearch{PrimaryKeys: primaryKeys}
searchJson, err := json.Marshal(searchModel)
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
pipeline.Set(tx.Statement.Context, hsetKey, searchJson, e.opt.Expires)
for key, value := range objectMap {
modelJson, err := json.Marshal(value)
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
modelKey := getModelKey(tx.Statement.Table, key)
pipeline.Set(tx.Statement.Context, modelKey, modelJson, e.opt.Expires+time.Second+3)
}
_, err = pipeline.Exec(tx.Statement.Context)
if err != nil {
e.opt.Logger.Error(err.Error())
}
}
// key的种类
// model model-primaryKey
// hash过期时间 model-EXPIRE-column
// where条件缓存 model-where-whereInfo{ whereValue:primaryList }
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/fmpt/fmgo.git
git@gitee.com:fmpt/fmgo.git
fmpt
fmgo
fmgo
v1.2.19

搜索帮助