gorm实现MySQL的INSERT INTO ... ON DUPLICATE KEY UPDATE差异化插入和更新

比如插入 f_create_uid,更新时忽略 f_create_uid,只更新 f_update_uid。可使用 gorm 的 BeforeCreate 和 BeforeUpdate 钩子,这两个钩子分别在创建和更新记录之前被调用。

// BeforeCreate 在创建记录之前调用
func (dob *MyStruct) BeforeCreate(tx *gorm.DB) (err error) {
    dob.CreateUid = // 设置创建人id
    dob.UpdateUid = // 设置更新人id
    // 使用 dob 值更新:
    //tx.Statement.SetColumn("f_create_uid", dob.CreateUid) // 钩子中被调用,第三个参数不需要指定为 true
    return
}

// BeforeUpdate 在更新记录之前调用
func (dob *MyStruct) BeforeUpdate(tx *gorm.DB) (err error) {
    dob.UpdateUid = // 设置更新人id
    return
}

注册和应用钩子:

// 注册钩子
db.Callback().Create().Before("gorm:create").Register("before_create", func(db *gorm.DB) {
    if dob, ok := db.Statement.Dest.(MyStruct); ok {
        dob.BeforeCreate(db)
    }
})

db.Callback().Update().Before("gorm:update").Register("before_update", func(db *gorm.DB) {
    if dob, ok := db.Statement.Dest.(MyStruct); ok {
        dob.BeforeUpdate(db)
    }
})

// 批量插入或更新(在冲突时更新除主键以外的所有列到新值)
db := tx.Model(&MyStruct{})
db = db.Omit("f_id", "f_update_time", "f_create_time", "f_memo")
db = db.Clauses(clause.OnConflict{UpdateAll: true})
err := db.Create(me).Error
if err != nil {
    fmt.Printf("InsertOrUpdate error: %s", err.Error())
    return nil, err
}

取消注册的钩子:

// 取消注册 BeforeCreate 钩子
db.Callback().Create().Before("gorm:create").Unregister("before_create")

// 取消注册 BeforeUpdate 钩子
db.Callback().Update().Before("gorm:update").Unregister("before_update")

示例:

package main

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type User struct {
    Id   int
    Name string
}

func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
    fmt.Printf("name: %s\n", u.Name)
    tx.Statement.SetColumn("name", u.Name)
    return
}

//func (u *User) BeforeSave(tx *gorm.DB) (err error) {
//    u.Name = "Sally"
//    return
//}

func main() {
    dsn := "user:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    // 注册 BeforeCreate 钩子
    db.Callback().Create().Before("gorm:create").Register("before_create", func(db *gorm.DB) {
        if user, ok := db.Statement.Dest.(*User); ok {
            user.BeforeCreate(db)
        }
    })

    // 注册 BeforeSave 钩子
    //db.Callback().Save().Before("gorm:save").Register("before_save", func(db *gorm.DB) {
    //    if user, ok := db.Statement.Dest.(*User); ok {
    //        user.BeforeSave(db)
    //    }
    //})

    db.AutoMigrate(&User{})
    user := User{
        Name: "Blake",
    }
    err = db.Create(&user).Error
    if err != nil { 
        panic(err)
    }
    fmt.Println(user.Name)
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 是一款广受欢迎的开源关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,现隶属于美国甲骨文公司(Oracle)。自1998年首次发布以来,MySQL以其卓越的性能、可靠性和可扩展性,成为全球范围内Web应用程序、企业级解决方案以及其他各种数据处理场景的首选数据库平台之一。 以下是对MySQL数据库的详细介绍: 核心特性与优势 开源与跨平台 MySQL遵循GPL开源协议,这意味着任何人都可以免费下载、使用和修改其源代码。这种开放性促进了广泛的社区支持和第三方插件、工具的发展。此外,MySQL支持多种操作系统,包括Windows、Linux、macOS、Solaris等,确保了其在不同环境下的兼容性和部署灵活性。 关系型模型与SQL支持 MySQL基于关系型数据库模型,数据以表格形式组织,并通过预定义的键(如主键、外键)在表之间建立关联。它完全支持结构化查询语言(SQL),允许用户进行数据查询、插入更新、删除、创建和管理数据库结构等操作。SQL标准的广泛支持使得MySQL易于学习,且与其他关系型数据库系统有良好的互操作性。 存储引擎 MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY等,每种引擎都有特定的优势和适用场景。例如,InnoDB提供事务安全、行级锁定和外键约束,适合处理高并发事务性的应用;MyISAM则更侧重于读取密集型操作,提供全文索引支持,适用于读多写少的场景。这种多引擎架构使得MySQL能够适应不同业务需求,提供高度定制化的存储解决方案。 性能与可扩展性 MySQL通过高效的缓存机制、查询优化器以及对硬件资源的有效利用,保证了在高负载情况下的稳定性和快速响应。它支持水平扩展(如通过分片、复制等技术)和垂直扩展(如增加硬件资源),以应对大规模数据存储和高并发访问的需求。 安全性与管理工具 MySQL提供了一系列安全措施,如用户账户管理、访问权限控制、SSL/TLS加密连接、审计日志等功能,确保数据的安全性和合规性。同时,MySQL附带了一系列管理工具,如MySQL Server、MySQL Workbench、MySQL Shell等,便于用户进行数据库配置、监控、备份、恢复、迁移等工作。 社区与生态系统

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值