golang gorm implements addition, deletion and modification of general single tables through generics

golang gorm implements general single table addition, deletion and modification through generics

No nonsense, just jump into the code

If you want to achieve universality, you must first implement universal query, which can be achieved by passing 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
}
}

Calling method

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

print 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

General query

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( & amp;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 & amp; & amp; includeDel[0] == true {
db.Unscoped()
} else {
db.Where("delete_time = 0")
}
err = db.Find( & amp;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( & amp;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 & amp; & amp; includeDel[0] == true {
db.Unscoped()
} else {
db.Where("delete_time = 0")
}
err = db.Find( & amp;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
}

Give examples of calling methods

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")
\t\t
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( & amp;tableModel, "id", "update_time")

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

You can write other flexible usage methods according to the code
Finish