golang gorm通过泛型实现通用单表增删改

作者: adm 分类: go 发布时间: 2024-04-17

golang gorm通过泛型实现通用单表增删改
无废话,直接上代码

想实现通用,首先得实现查询的通用,可以用传递map实现

func Where(where map[string]interface{}) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		dbTmp := db
		for ko, value := range where {
			koSlice := strings.Split(ko, "#")
			var key, op string
			if len(koSlice) == 1 {
				key = ko
				if php2go.InArray(key, []string{"select", "order", "offset", "limit"}) {
					op = ko
				} else {
					op = "eq"
				}
			} else {
				key = koSlice[0]
				op = koSlice[1]
			}
			switch op {
			case "eq":
				dbTmp.Where(key+" = ?", value)
			case "neq":
				dbTmp.Where(key+" != ?", value)
			case "gt":
				dbTmp.Where(key+" > ?", value)
			case "gte":
				dbTmp.Where(key+" >= ?", value)
			case "lt":
				dbTmp.Where(key+" < ?", value)
			case "lte":
				dbTmp.Where(key+" <= ?", value)
			case "like":
				dbTmp.Where(key+" like ?", "%"+value.(string)+"%")
			case "in":
				dbTmp.Where(key+" in ?", value)
			case "notin":
				dbTmp.Where(key+" not in ?", value)
			case "between":
				dbTmp.Where(key+" between ? and ?", value.([]int)[0], value.([]int)[1])
			case "betweens":
				dbTmp.Where(key+" between ? and ?", value.([]string)[0], value.([]string)[1])
			case "select":
				dbTmp.Select(value.(string))
			case "order":
				dbTmp.Order(value.(string))
			case "offset":
				dbTmp.Offset(value.(int))
			case "limit":
				dbTmp.Limit(value.(int))
			}
		}
		return dbTmp
	}
}

调用方式

examleWhere := map[string]interface{}{
				"name#like":           data.ToUserName,
				"id":        		   data.UserID,
				"create_time#between": []int{17000000, 18000000},
				"grade#in":            []int{3,4},
				"order":               "id desc",
			}
Gorm().Table("xxx").Scopes(Where(examleWhere)).xxx

打印 sql:

select * from xxx where name like "%xx%" and id = xxx and create_time between 17xxx and 18xxx and grade in (3,4) order by id desc

通用查询

type FieldType interface {
	uint | uint8 | uint16 | uint32 | uint64 | int | int8 | int16 | int32 | int64 | float32 | float64 | string
}
func Get[T any](where map[string]interface{}, field ...string) (ret T, err error) {
	db := sys.Gorm().Scopes(Where(where)).Where("delete_time = 0")
	if len(field) > 0 {
		db.Select(field)
	}
	err = db.Find(&ret).Error
	return
}

func GetVal[T FieldType](tableName string, where map[string]interface{}, field string, includeDel ...bool) (ret T, err error) {
	db := sys.Gorm().Table(tableName).Scopes(Where(where)).Select(field)
	if len(includeDel) > 0 && includeDel[0] == true {
		db.Unscoped()
	} else {
		db.Where("delete_time = 0")
	}
	err = db.Find(&ret).Error
	return
}

func Gets[T any](where map[string]interface{}, field ...string) (ret []T, err error) {
	db := sys.Gorm().Scopes(Where(where)).Where("delete_time = 0")
	if len(field) > 0 {
		db.Select(field)
	}
	err = db.Find(&ret).Error
	return
}

func GetSlice[T FieldType](tableName string, where map[string]interface{}, field string, includeDel ...bool) (ret []T, err error) {
	ret = make([]T, 0)
	db := sys.Gorm().Table(tableName).Scopes(Where(where)).Select(field)
	if len(includeDel) > 0 && includeDel[0] == true {
		db.Unscoped()
	} else {
		db.Where("delete_time = 0")
	}
	err = db.Find(&ret).Error
	return
}

func Update[T any](where map[string]interface{}, update T) (err error) {
	db := sys.Gorm()
	err = db.Scopes(Where(where)).Updates(update).Error
	return
}

func UpdateByMap(table string, where, update map[string]interface{}) (err error) {
	db := sys.Gorm().Table(table)
	err = db.Scopes(Where(where)).Updates(update).Error
	return
}

func UpdateByMapTx(tx *gorm.DB, table string, where, update map[string]interface{}) (err error) {
	db := tx.Table(table)
	err = db.Scopes(Where(where)).Updates(update).Error
	return
}

// Create
// doUpdate: on duplicate key update : all, []string{}...
func Create[T any](data *[]T, doUpdate ...string) (err error) {
	var db *gorm.DB
	if len(doUpdate) > 0 {
		if doUpdate[0] == "all" {
			db = sys.Gorm().Clauses(clause.OnConflict{
				UpdateAll: true,
			}).Scopes()
		} else {
			db = sys.Gorm().Clauses(clause.OnConflict{
				DoUpdates: clause.AssignmentColumns(doUpdate),
			}).Scopes()
		}
	} else {
		db = sys.Gorm().Scopes()
	}
	err = db.Create(&data).Error
	return
}

func CreateTx[T any](tx *gorm.DB, data *T, doUpdate ...string) (err error) {
	if len(doUpdate) > 0 {
		if doUpdate[0] == "all" {
			tx.Clauses(clause.OnConflict{
				UpdateAll: true,
			}).Scopes()
		} else {
			tx.Clauses(clause.OnConflict{
				DoUpdates: clause.AssignmentColumns(doUpdate),
			}).Scopes()
		}
	}
	err = tx.Create(&data).Error
	return
}

func CreatesTx[T any](tx *gorm.DB, data *[]T, doUpdate ...string) (err error) {
	if len(doUpdate) > 0 {
		if doUpdate[0] == "all" {
			tx.Clauses(clause.OnConflict{
				UpdateAll: true,
			}).Scopes()
		} else {
			tx.Clauses(clause.OnConflict{
				DoUpdates: clause.AssignmentColumns(doUpdate),
			}).Scopes()
		}
	}
	err = tx.Create(&data).Error
	return
}

给出调用方式案例

model.Get[model.WwStaff](map[string]interface{}{"corp_id": req.CorpId, "userid": req.StaffUserid})

model.GetVal[int]("table_name", map[string]interface{}{
			"corp_id":     corpId,
			"dept_id":     deptId,
			"delete_time": 0,
		}, "parentid")
		
model.GetSlice[int64]("table_name",map[string]interface{}{"staff_id": req.Id}, "id")

// insert ...
model.Create(&tableModel)
// insert ... ON DUPLICATE KEY UPDATE id = VALUES(id) ......
model.Create(&tableModel, "id", "update_time")

model.UpdateByMap("table_name",
			map[string]interface{}{"id#in": roomUnionIds},
			map[string]interface{}{"upload": 2})
			
model.UpdateByMapTx(tx, "table_name",
			map[string]interface{}{"id#in": roomUnionIds},
			map[string]interface{}{"upload": 2})

可以依照代码,写出其它灵活的使用方式

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!