gorm中如何解决零值更新的问题

文章介绍了在GormORM框架中遇到的更新字段时只修改非零值的问题,通过引入sql.NullString类型来解决,确保空值不会被误更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

在gorm快速入门中的这一行代码:

type Product struct {
  gorm.Model
  Code  string
  Price uint
}
// 迁移 schema
  db.AutoMigrate(&Product{})

// Create
  db.Create(&Product{Code: "", Price: 100})
// Update
  db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // 仅更新非零值字段

注释中写道进更新非零值字段,意味着如果Code的值如果为空就无法更新。

解决办法

在gorm中有sql.NullString类型如下:

type NullString struct {
	String string
	Valid  bool // Valid is true if String is not NULL
}

类型中包含String类型和bool类型,string类型用于存储值,bool类型为true时表示值为空值

解决后的代码如下:

package main

import (
	"database/sql"
	"log"
	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

func main() {

	dsn := "root:qweasdzxc321@tcp(127.0.0.1:3306)/grom_test?charset=utf8mb4&parseTime=True&loc=Local"

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger})
	if err != nil {
		panic(err)
	}

	//定义一个表结构,将表结构智界生成对应的表
	type Product struct {
		gorm.Model
		Code  sql.NullString
		Price uint
	}
	// 迁移 schema
	db.AutoMigrate(&Product{}) //此处应该有sql语句

	// 新增
	db.Create(&Product{Code: sql.NullString{"D42", true}, Price: 100})

	
	// Update - 更新多个字段
	db.Model(&product).Updates(Product{Price: 200, Code: sql.NullString{"F42", true}}) // 仅更新非零值字段
	

	 Delete - 删除 product
	//db.Delete(&product, 1)

}

通过gorm中sql.NullString类型我们可以解决零值更新问题!

### GORM 官方文档与使用教程 官方文档是学习任何框架的最佳起点之一。对于 GORM,其官方文档提供了详尽的内容覆盖从基础安装到高级功能的各个方面[^1]。 #### 1. **GORM 的安装** 要开始使用 GORM,首先需要将其安装至您的项目环境中。可以通过以下命令完成安装: ```bash go get -u gorm.io/gorm go get -u gorm.io/driver/mysql ``` 这些命令分别用于安装核心库 `gorm` 和 MySQL 数据库驱动支持。 #### 2. **基本配置与初始化** 在实际应用中,通常会在项目的根目录下创建一个入口文件(如 `main.go`),并通过它实现数据库连接和其他必要的设置。下面是一个简单的例子: ```go package main import ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) func main() { db, err := gorm.Open("mysql", "root:admin@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local") if err != nil { fmt.Println(err) panic("failed to connect database") } defer db.Close() // 开启调试模式以查看 SQL 查询日志 db.LogMode(true) fmt.Println("Database connection successful!") } ``` 上述代码展示了如何建立与 MySQL 数据库的连接,并启用查询日志以便于开发阶段排查问题[^2]。 #### 3. **数据更新机制** 当利用结构体 (`struct`) 进行记录更新时,默认情况下仅非会被写入数据库。为了更精确地控制哪些字段应该被更新,可以采用两种方式解决问题:一是通过 `Select()` 方法显式指定待更新字段;二是借助映射表形式传递参数[^3]。 例如,假设我们有一个模型定义如下所示: ```go type User struct { ID uint Name string Age int } ``` 那么针对特定用户的年龄修改操作可表述为: ```go db.Model(&User{}).Where("id = ?", userId).Update("age", newAge) ``` 或者更加灵活的方式——传入键对集合: ```go updates := map[string]interface{}{ "name": "newName", "age": 25, } db.Model(&User{}).Where("id = ?", userId).Updates(updates) ``` #### 4. **立即执行方法概述** 所谓“立即执行方法”,指的是那些一旦调用就会即时生成并提交对应 SQL 请求给底层存储引擎的行为。这类函数主要包括但不限于增删改查四大类操作中的具体表现形式[^4]。 以下是几个常见的实例演示: - 插入新纪录: ```go user := User{Name: "John Doe", Age: 30} result := db.Create(&user) if result.Error != nil { fmt.Printf("Error occurred while creating user:%v\n", result.Error) } else { fmt.Printf("New record created with ID=%d\n", user.ID) } ``` - 移除现有项: ```go deletedRowsCount := db.Delete(&User{}, userId).RowsAffected fmt.Printf("%d rows were deleted.\n", deletedRowsCount) ``` ### 结论 综上所述,无论是初学者还是有一定经验的技术人员,在探索像 GORM 这样的 ORM 工具过程中都离不开对其官方指南的学习以及实践验证过程中的不断总结积累。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值