123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- // 数据库底层操作接口
- // 秒寻科技
- // zt 2024-01-04
- package mysqlapi
- import (
- "encoding/json"
- "errors"
- "fmt"
- "ipsomc/core/dao/mysql/mysqlmodel"
- "ipsomc/util"
- "reflect"
- "strings"
- "time"
- "github.com/jinzhu/gorm"
- _ "github.com/jinzhu/gorm/dialects/mysql"
- )
- type MySqlApi struct {
- }
- // 全局数据库操作对象
- var (
- Db *gorm.DB
- )
- // 初始化数据库模块,创建一个数据连接对象
- func OpenSqlDb() error {
- var err error
- myViper := util.GetViper()
- dbHostAddress := myViper.GetString("dbDefault.dbHost") //主机地址
- dbHostPort := myViper.GetString("dbDefault.dbPort") //主机端口
- dbName := myViper.GetString("dbDefault.dbName") //数据库名
- dbUser := myViper.GetString("dbDefault.dbUser") //数据库用户名
- dbPassword := myViper.GetString("dbDefault.dbPassword") //数据库用户登录密码
- //组织dsn字符串
- dsn := dbUser + ":" + dbPassword + "@tcp(" + dbHostAddress + ":" + dbHostPort + ")/" + dbName + "?charset=utf8mb4&parseTime=True&loc=Local"
- //连接数据库
- for Db, err = gorm.Open("mysql", dsn); err != nil; {
- fmt.Println("连接数据库异常,之后自动重连")
- time.Sleep(5 * time.Second)
- Db, err = gorm.Open("mysql", dsn)
- }
- Db.LogMode(true) //打开日志开关
- Db.SingularTable(true) //禁用数据库表名复数
- TimerConnectSqlDb(Db) //5秒定时连接数据库,以免连接断开
- return nil
- }
- // CloseDb 关闭数据
- func CloseSqlDb() {
- Db.Close() //关闭数据
- }
- // GetDb 返回当前db对象
- func (obj *MySqlApi) GetDb() *gorm.DB {
- return Db
- }
- // 创建数据库表,不会删除和修改数据库中的数据,只增加新新的表字段
- func (obj *MySqlApi) GenerateDbTable(dataModel interface{}) {
- Db.AutoMigrate(dataModel)
- }
- // TimerConnectSqlDb 定时连接数据库
- func TimerConnectSqlDb(db *gorm.DB) {
- go func() {
- myTiker := time.NewTicker(30 * time.Second)
- for range myTiker.C {
- var dtTime time.Time
- if err := db.Raw("select now() as time").Scan(&dtTime).Error; err != nil {
- fmt.Println(err)
- }
- }
- }()
- }
- // AddItem 增加数据库记录
- func (obj *MySqlApi) AddItem(dataModel interface{}) error {
- if err := Db.Create(dataModel).Error; err != nil {
- return err
- }
- return nil
- }
- // UpdateItem 更新记录
- func (obj *MySqlApi) UpdateItem(dataModel interface{}, dataMap map[string]interface{}) error {
- val := reflect.ValueOf(dataModel)
- if val.Kind() != reflect.Ptr {
- return errors.New("更新失败,函数参数检查错误,应为指针类型")
- }
- val = val.Elem()
- if val.Kind() != reflect.Struct {
- return errors.New("更新失败,函数参数检查错误,应为结构体指针类型")
- }
- id := val.FieldByName("ID").Int()
- if id == 0 {
- return errors.New("更新失败,请设置要更新的数据的ID值")
- }
- //更新数据
- if err := Db.Model(dataModel).Updates(dataMap).Error; err != nil {
- return err
- }
- return nil
- }
- // DeleteItem 删除记录
- func (obj *MySqlApi) DeleteItem(dataModel interface{}) error {
- val := reflect.ValueOf(dataModel)
- if val.Kind() != reflect.Ptr {
- return errors.New("删除失败,函数参数检查错误,应为指针类型")
- }
- val = val.Elem()
- if val.Kind() != reflect.Struct {
- return errors.New("删除失败,函数参数检查错误,应为结构体指针类型")
- }
- id := val.FieldByName("ID").Int()
- if id == 0 {
- return errors.New("删除失败,请设置要删除的数据的ID值")
- }
- if err := Db.Where("owner_id <> 0").Delete(dataModel).Error; err != nil {
- return err
- }
- return nil
- }
- // GetItemByID 根据id获得记录数据
- func (obj *MySqlApi) GetItemByID(dataModel interface{}) error {
- val := reflect.ValueOf(dataModel)
- if val.Kind() != reflect.Ptr {
- return errors.New("查询数据失败,函数参数检查错误,应为指针类型")
- }
- val = val.Elem()
- if val.Kind() != reflect.Struct {
- return errors.New("查询数据失败,函数参数检查错误,应为结构体指针类型")
- }
- id := val.FieldByName("ID").Int()
- if id == 0 {
- return errors.New("查询数据失败,请设置要查询的数据的ID值")
- }
- if err := Db.First(dataModel).Error; err != nil {
- return err
- }
- return nil
- }
- // 组织公司参数(公司ID和项目ID)
- func (obj *MySqlApi) GenerateCompanyParam(db *gorm.DB, companyId int, projectId int) *gorm.DB {
- if companyId > 0 {
- db = db.Where("company_id=?", companyId)
- }
- if projectId > 0 {
- db = db.Where("project_id=?", projectId)
- }
- return db
- }
- // 组织search参数
- func (obj *MySqlApi) GenerateSearchParam(db *gorm.DB, searchParam map[string]interface{}, dataMap map[string]interface{}) *gorm.DB {
- //组织Search参数
- for queryKey, value := range searchParam {
- queryKey = strings.ToLower(queryKey)
- for mapKey := range dataMap {
- mapKey = strings.ToLower(mapKey)
- if mapKey == queryKey {
- db = db.Where(queryKey+"=?", value)
- }
- }
- }
- return db
- }
- // 组织Query参数
- func (obj *MySqlApi) GenerateQueryParam(db *gorm.DB, queryParam []mysqlmodel.QueryParam, dataMap map[string]interface{}) *gorm.DB {
- wLen := len(queryParam)
- for i := 0; i < wLen; i++ {
- obj := queryParam[i]
- for mapKey := range dataMap {
- mapKey = strings.ToLower(mapKey)
- queryKey := strings.ToLower(obj.Key)
- if mapKey == queryKey {
- if obj.Opt == "like" {
- db = db.Where(queryKey+" like ?", fmt.Sprintf("%v", obj.Data)) //%通配在前端处理
- } else if obj.Opt == "in" {
- db = db.Where(queryKey+" in (?)", obj.Data)
- } else {
- db = db.Where(queryKey+obj.Opt+"?", obj.Data)
- }
- }
- }
- }
- return db
- }
- // 组织Order参数
- func (obj *MySqlApi) GenerateOrderParam(db *gorm.DB, orderBy string) *gorm.DB {
- strOrderBy := orderBy
- if len(strOrderBy) > 0 {
- orderList := strings.Split(strOrderBy, ",")
- for _, item := range orderList {
- db = db.Order(item)
- }
- } else {
- db = db.Order("id") //默认按照ID排序
- }
- return db
- }
- // 组织查询条件where参数
- func (obj *MySqlApi) GenerateWhereParam(dataModel interface{}, companyId int, projectId int, searchParam map[string]interface{}, queryParam []mysqlmodel.QueryParam, orderParam string) *gorm.DB {
- //空接口转map,以便判断查询字段是否在模型
- dataMap := make(map[string]interface{})
- byteList, _ := json.Marshal(dataModel)
- json.Unmarshal(byteList, &dataMap)
- db := obj.GetDb()
- db = obj.GenerateCompanyParam(db, companyId, projectId) //组织公司ID参数
- db = obj.GenerateSearchParam(db, searchParam, dataMap) //组织Search参数
- db = obj.GenerateQueryParam(db, queryParam, dataMap) //组织query参数
- db = obj.GenerateOrderParam(db, orderParam) //组织排序参数
- return db
- }
- // 查询
- func (obj *MySqlApi) GetItemList(dataModel interface{}, listParam *mysqlmodel.ListParam, dataList interface{}) error {
- val := reflect.ValueOf(dataModel)
- if val.Kind() != reflect.Ptr {
- return errors.New("查询数据失败,函数参数检查错误,应为指针类型")
- }
- val = val.Elem()
- if val.Kind() != reflect.Struct {
- return errors.New("查询数据失败,函数参数检查错误,应为结构体指针类型")
- }
- //组织查询条件
- db := obj.GenerateWhereParam(dataModel, listParam.CompanyID, listParam.ProjectID, listParam.Search, listParam.Query, listParam.OrderBy)
- //查询数据
- if err := db.Find(dataList).Error; err != nil {
- return errors.New("查询数据失败")
- }
- return nil
- }
- // 分页查询
- func (obj *MySqlApi) GetPageItemList(dataModel interface{}, listParam *mysqlmodel.PageListParam, dataList interface{}) (mysqlmodel.PageListData, error) {
- pageListData := mysqlmodel.PageListData{}
- pageListData.PageNum = listParam.PageNum
- pageListData.PageSize = listParam.PageSize
- offset := (listParam.PageNum - 1) * listParam.PageSize
- pageSize := listParam.PageSize
- //组织查询条件
- db := obj.GenerateWhereParam(dataModel, listParam.CompanyID, listParam.ProjectID, listParam.Search, listParam.Query, listParam.OrderBy)
- //获得分页数据
- if err := db.Limit(pageSize).Offset(offset).Find(dataList).Error; err != nil {
- return pageListData, err
- }
- pageListData.Items = dataList
- //计算总记录数
- value := reflect.ValueOf(dataList).Elem()
- if listParam.PageNum == 1 && value.Len() < listParam.PageSize { //记录数不足一页
- pageListData.TotalCount = value.Len()
- } else {
- db.Model(dataModel).Count(&pageListData.TotalCount)
- }
- return pageListData, nil
- }
|