You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
4.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package DaoCache
import (
"dsSso/Const/ErrorConst"
"dsSso/Model"
"dsSso/Utils/CommonUtil"
"dsSso/Utils/DbUtil"
"dsSso/Utils/LogUtil"
"dsSso/Utils/RedisUtil"
"fmt"
"github.com/go-redis/redis/v7"
"reflect"
"strconv"
"time"
)
var db = DbUtil.Engine
/**
功能:优先从缓存读取,检查到缺失的,就从数据库读取,然后两个结果集拼接后返回,同时将缺失的缓存补全
作者:黄海
时间2020-02-05
*/
func GetListByIds(ids []string, m Model.Selector) []map[string]interface{} {
//1、第一步从缓存读取
list, notExistsIds := batchReadRedis(ids, m.RedisPrefix)
//2、如果有一些ID在缓存中不存在那么需要从数据库中查询然后填充到缓存中
if notExistsIds != nil && len(notExistsIds) > 0 {
//从数据库中获取缺失的数据
lostCacheList := fromDb(notExistsIds, m)
//缓存写入
batchWriteRedis(lostCacheList, m)
//合并两个结果集
for i := 0; i < len(lostCacheList); i++ {
list = append(list, lostCacheList[i])
}
}
return list
}
/*===================以下为内部函数用于扩展从REDIS缓存中查询===========================*/
func fromDb(ids []string, m Model.Selector) []map[string]interface{} {
tableName := m.TableName
pkField := m.PkField
//查询数据库
var idsStr = ""
for i := 0; i < len(ids); i++ {
idsStr = idsStr + "," + ids[i]
}
if len(idsStr) > 0 {
idsStr = idsStr[1:]
}
results, err := db.SQL(`select * from `+tableName+` where find_in_set(`+pkField+`,?)`, idsStr).Query().List()
if err != nil {
LogUtil.Error(ErrorConst.SqlQueryError, "从数据库中读取数据失败:"+err.Error())
}
return results
}
/**
功能:批量写入缓存
作者:黄海
时间2020-02-05
*/
func batchWriteRedis(list []map[string]interface{}, m Model.Selector) {
pkField := m.PkField
prefix := m.RedisPrefix
//声明管道
pipe := RedisUtil.RedisClient.Pipeline()
for i := 0; i < len(list); i++ {
bean := list[i]
var pkSuffix = ""
switch bean[pkField].(type) {
case string:
pkSuffix = bean[pkField].(string)
case int64:
pkSuffix = strconv.FormatInt(reflect.ValueOf(bean[pkField]).Int(), 10)
}
key := prefix + pkSuffix
pipe.HSet(key, bean)
pipe.Expire(key, 24*time.Hour)
}
//执行管道
pipe.Exec()
}
/**
功能从REDIS中批量获取指定ID的列表信息
作者:黄海
时间2020-02-05
*/
func batchReadRedis(ids []string, prefix string) ([]map[string]interface{}, []string) {
//1、创建管道
var list []*redis.StringStringMapCmd
pipe := RedisUtil.RedisClient.Pipeline()
for i := 0; i < len(ids); i++ {
list = append(list, pipe.HGetAll(prefix+ids[i]))
}
//2、执行管道
_, err := pipe.Exec()
if err != nil {
LogUtil.Error(ErrorConst.SqlQueryError, err.Error())
}
//存在于缓存中的数据
var existList []map[string]interface{}
//3、输出结果
//不存在的主键有哪些
var notExistsIds []string
for i := 0; i < len(list); i++ {
_bean := list[i].Val()
if len(_bean) > 0 {
//将values转成Interface{},其实这个锅 Golang是不背的因为redis中hset写入的整数取出来hget也是字符串~
n := CommonUtil.ConvertMapStringToMapInterface(_bean)
//找到了加到返回值列表中去
existList = append(existList, n)
} else {
notExistsIds = append(notExistsIds, ids[i])
}
}
//返回值
return existList, notExistsIds
}
/**
功能将指定的SQL语句计算分页的SQL
作者:黄海
时间2020-03-25
*/
func PageData(baseSql string, model Model.Selector, args ...interface{}) ([]map[string]interface{}, int32) {
//条件查询语句
conditionSql := fmt.Sprintf("%s %s %s", " order by ", model.PkField, " limit ? offset ? ")
//分页的语句
pageSql := fmt.Sprintf("%s %s", baseSql, conditionSql)
//分页数据
list, err := db.SQL(pageSql, args...).Query().List()
if err != nil {
LogUtil.Error(ErrorConst.SqlQueryError, err.Error())
}
//总数
list2, err := db.SQL(baseSql, args...).Query().List()
if err != nil {
LogUtil.Error(ErrorConst.SqlQueryError, err.Error())
}
//有哪些ids?
var ids = CommonUtil.Ids(list, model.PkField)
//-->缓存层-->数据库-->缓存
list = GetListByIds(ids, model)
return list, int32(len(list2))
}