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

这篇具有很好参考价值的文章主要介绍了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})

可以依照代码,写出其它灵活的使用方式
结束文章来源地址https://www.toymoban.com/news/detail-742985.html

到了这里,关于golang gorm通过泛型实现通用单表增删改的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构之顺序表增删改查操作实现

           线性表是具有 相同 数据类型的n(n=0)个数据元素的 有限 序列      顺序表 ---用顺序存储的方式实现线性表。顺序存储---把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。      如何知道一个数据元素大小

    2024年02月16日
    浏览(33)
  • 数据结构之带头节点的单链表增删改查操作实现

            单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。       单链表的各个数据元素在物理上可以是离散存放的,每个结点除了存放数据元素外,还要存储指向下一个节点的指针。而顺序表是连续存放的,每个结点中只存放数据元

    2024年02月16日
    浏览(32)
  • Golang通过Gorm操作Mysql时遇到的datetime时区问题

    golang使用Gorm操作MySQL,MySQL中数据类型是datetime,Golang中用的是time.now。 但是会导致存储的时间与北京时间有8h误差, 显然是没有初始化时区导致。 参考我自己之前写过的一篇总结——Mysql中多种日期类型——DATETIME、TIMESTAMP、TIME、YEAR、DATE的区分 datetime是给什么就存什么,

    2024年01月20日
    浏览(31)
  • 使用 GORM 连接数据库并实现增删改查操作

    首先,我们需要安装 GORM 包。在终端中运行以下命令: shell go get -u gorm.io/gorm 在 Go 代码的开头导入以下包: 在代码中建立数据库连接,示例中使用 MySQL 数据库作为示范: 请确保替换 user 、 password 和 dbname 为你的实际数据库凭据和名称。 在 GORM 中,我们需要定义模型结构来

    2024年02月15日
    浏览(40)
  • gin+gorm增删改查目录框架

    从网上找资料,发现,很多都是直接的结构 路由,后端的controller层,还有model层,都是放在了同一个main.go文件中,如果写项目的话,还得自己去拆文件,拆代码,经过查询和自己总结,下面放一个目录框架 总体目录结构 按照业务流程顺序,解释说明 1、加载自定义封装函数文

    2024年01月19日
    浏览(34)
  • MyBatis 单表的增删改查

    ✅作者简介:2022年 博客新星 第八 。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:SSM 框架从入门到精通 ✨特色专栏:国学周更-心性养成之路 🥭本文内容:MyBatis 单表的增删

    2024年02月21日
    浏览(30)
  • 数据湖架构Hudi(二)Hudi版本0.12源码编译、Hudi集成spark、使用IDEA与spark对hudi表增删改查

    Hadoop 3.1.3 Hive 3.1.2 Flink 1.13.6,scala-2.12 Spark 3.2.2,scala-2.12 2.1.1 环境准备 2.1.2 下载源码包 2.1.3 在pom文件中新增repository加速依赖下载 在pom文件中修改依赖的组件版本: 2.1.4 修改源码兼容hadoop3并添加kafka依赖 Hudi默认依赖的hadoop2,要兼容hadoop3,除了修改版本,还需要修改如下代

    2024年02月06日
    浏览(44)
  • golang操作数据库--gorm框架、redis

    ①引入 ②初始化 ③增删改查 官网: http://gorm.io/ ①引入 ②初始化 ③增删改查 说明:Debug()可以查看执行的sql语句。 ④gorm gen的使用 a.先安装 (会安装到gopath的bin目录下,windows电脑,需要将该路径加入到系统路径) eg : b.举例: 说明1:windows电脑go install之后,把exe添加到系统路

    2024年02月10日
    浏览(30)
  • Golang Gorm 一对多查询 preload预加载

     GORM允许使用  Preload 通过多个SQL中来直接加载关系, 例如: 其实很简单, 你要preload  user表 的数据,gorm就提前把这张表全部取出来,然后再执行 First 或 Find 这样的方法去查询主数据,最后把两种数据通过外键关联一一对应起来。 其实preload也就是做了两次查询。    有了

    2024年02月11日
    浏览(32)
  • Golang Gorm 更新字段 save、update、updates

    更新和删除操作的前提条件都是要在找到数据的情况下,先要查询到数据才可以做操作。 更新的前提的先查询到记录, Save保存所有字段,用于单个记录的全字段更新 ,它会保控所有字段,即使零值也会保存。 在更新和删除之前,要利用之前学的查询语句先查询到数据,再

    2024年02月03日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包