当前位置: 首页 > news >正文

gorm高级使用-自动生成创建人和更新人

一、业务介绍

  • 1、有时候我们希望每次在数据的创建和更新的时候都保留当前操作人信息,最简单暴力的方式就是在每次创建的时候手动插入,在修改的时候手动的修改,这种方式可以实现,但是比较笨和费力
  • 2、也可以尝试使用gorm的钩子函数来实现这个功能,并且钩子函数要接收上下文参数,将本次接口请求的用户数据插入到对应的字段上

二、使用gorm自定义全局钩子来实现自动插入创建人、自动修改更新人操作

  • 1、创建一个文件实现接收上下文参数来实现自动插入数据,关于CreatedNameUpdatedName自己根据实际数据库字段修改

    package gormPlus
    
    import "gorm.io/gorm"
    
    const UserIDKey string = "user_name"
    
    func BeforeCreate(db *gorm.DB) {
    	if userName, ok := db.Statement.Context.Value(UserIDKey).(string); ok {
            // 多加这个判断主要是判断如果表字段有created_name的时候才会给这个字段赋值,没有也不影响
    		if db.Statement.Schema.LookUpField("CreatedName") != nil {
    			db.Statement.SetColumn("CreatedName", userName)
    		}
    		if db.Statement.Schema.LookUpField("UpdatedName") != nil {
    			db.Statement.SetColumn("UpdatedName", userName)
    		}
    	}
    }
    
    func BeforeUpdate(db *gorm.DB) {
    	if userName, ok := db.Statement.Context.Value(UserIDKey).(string); ok {
    		if db.Statement.Schema.LookUpField("UpdatedName") != nil {
    			db.Statement.SetColumn("UpdatedName", userName)
    		}
    	}
    }
    
    // RegisterAutoHooks 注册全局钩子
    func RegisterAutoHooks(db *gorm.DB) {
    	db.Callback().Create().Before("gorm:before_create").Register("audit_hook:before_create", BeforeCreate)
    	db.Callback().Update().Before("gorm:before_update").Register("audit_hook:before_update", BeforeUpdate)
    }
    
    
  • 2、全局挂载注册钩子函数

    sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s",
        "root",
        "123456",
        "localhost",
        "3306",
        "test2",
    )
    fmt.Println("数据库连接:", sqlStr)
    
    db, err := gorm.Open(mysql.Open(sqlStr), &gorm.Config{
        Logger:                                   logger.Default.LogMode(logger.Info),
        DisableForeignKeyConstraintWhenMigrating: true, // 自动创建表的时候不创建外键
        NamingStrategy: schema.NamingStrategy{ // 自动创建表时候表名的配置
            SingularTable: true,
            // 全部的表名前面加前缀
            //TablePrefix: "mall_",
        },
    })
    if err != nil {
        fmt.Println("打开数据库失败", err)
        panic("打开数据库失败" + err.Error())
    }
    
    // 注册创建人、更新人钩子
    gormPlus.RegisterAutoHooks(db)
    
  • 3、手动来验证

    type User2 struct {
    	ID        int64  `gorm:"primaryKey"`
    	Name      string `gorm:"size:255"`
    	CreatedName int64  `gorm:"column:created_name"` // 创建人
    	UpdatedName int64  `gorm:"column:updated_name"` // 更新人
    }
    
    ctx := context.WithValue(context.Background(), UserIDKey, "李四")
    
    // 插入数据
    user := User2{Name: "John Doe"}
    db.WithContext(ctx).Create(&user) // 自动填充 CreatedName = 李四, UpdatedName = 李四
    
    

二、结合gin项目操作

  • 1、在实际项目中操作人主要是从当前请求的token解析出操作人

  • 2、自定义一个函数来获取上下文的token,然后从redis中读取到数据

    func GetCtx(ctx *gin.Context) context.Context {
    	token := ctx.GetHeader("token")
    	fmt.Println(token, "当前token")
    	// TODO 根据token获取用户名,这里假设用户名是admin
    	return context.WithValue(context.Background(), gormPlus.UserIDKey, "admin")
    }
    
    
  • 3、在接口里面使用当前的上下文操作数据库

    package api
    
    import (
    	"github.com/gin-gonic/gin"
    	"gorm.io/gorm"
    	"gorm_plus_gin/model"
    	"gorm_plus_gin/utils"
    )
    
    type IAccount interface {
    	CreateAccountApi(ctx *gin.Context)     // 创建账号
    	ModifyAccountByIdApi(ctx *gin.Context) // 根据id修改账号
    
    }
    
    type Account struct {
    	db *gorm.DB
    }
    
    func (a Account) CreateAccountApi(ctx *gin.Context) {
    	if err := a.db.WithContext(utils.GetCtx(ctx)).Create(&model.AccountEntity{
    		Username: "test",
    	}).Error; err != nil {
    		utils.Fail(ctx, "创建账号失败")
    		return
    	}
    	utils.Success(ctx, "创建账号成功")
    	return
    }
    
    func (a Account) ModifyAccountByIdApi(ctx *gin.Context) {
    	if err := a.db.WithContext(utils.GetCtx(ctx)).Model(&model.AccountEntity{}).Where("id = ?", 1).Update("Username", "莉莉丝").Error; err != nil {
    		utils.Fail(ctx, "修改账号失败")
    		return
    	}
    	utils.Success(ctx, "修改账号成功")
    }
    
    func NewIAccount(db *gorm.DB) IAccount {
    	return Account{
    		db: db,
    	}
    }
    
    

相关文章:

  • 数据结构篇——串(String)
  • MySQL 临时表
  • c语言笔记 getchar
  • PAT乙级(1091 N-自守数)C语言解析
  • 了解JVM
  • android viewmodel如何使用
  • 支付宝当面付java,php,sdk下载
  • 批量在 Word 的指定位置插入页,如插入封面、末尾插入页面
  • 玩转python:系统设计模式在Python项目中的应用
  • 第八章: go 的 map 类型:
  • Springboot全局LocalDateTime时间格式化配置
  • 【Tools】Windows下Git 2.48安装教程详解
  • ## DeepSeek写水果记忆配对手机小游戏
  • Flink之Barrier对齐会影响执行效率,怎么跳过Barrier对齐,跳过后还能保证‌Exactly-Once语义吗?
  • 周末总结(2024/03/08)
  • Java虚拟机之垃圾收集(一)
  • c++ 游戏入门指南
  • libilibi项目优化(1)使用Redis实现缓存
  • 考研机试常见基本题型
  • 学习前置知识第18和19天
  • 网站用axure做的rp格式/网站推广平台搭建
  • 网站做流量的论坛贴吧/搜索引擎排名机制
  • 重庆网站制作长沙/在线识别图片找原图
  • 自助建站和网站开发的利弊/天津百度整站优化服务
  • 网站的搜索引擎/百度seo工作室
  • 青海做网站最好的公司/seo关键词推广价格