golang gorm通过泛型实现通用单表增删改
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})
可以依照代码,写出其它灵活的使用方式