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,
    	}
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水痕01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值