当默认值为NUL时,如何防止GORM将空字符串写入MySQL?

How to prevent GORM from writing empty strings into MySQL when default is NULL?

提问人:wmc 提问时间:7/26/2023 最后编辑:Shadowwmc 更新时间:7/26/2023 访问量:181

问:

我正在使用 Go:Fiber 构建一个小型 RESTful API,并使用 GORM 来管理 MySQL 中的数据对象存储。我有一个表,其值设置为默认为 NULL,但是当我使用 GORM 更新该表中的记录时,将启动 NULL 值并放入空字符串。我已经将我的结构标记为默认 null,但仍然没有骰子。

这是我的数据结构。

type Person struct {
    gorm.Model
    ID         uuid.UUID `gorm:"type:char(36);primary_key"`
    AccountId  uuid.UUID `gorm:"default:null"`
    NamePrefix string    `gorm:"default:null"`
    NameFirst  string    `gorm:"index;default:null"`
    NameMiddle string    `gorm:"default:null"`
    NameLast   string    `gorm:"index;default:null"`
    NameSuffix string    `gorm:"default:null"`
    Notes      string    `gorm:"default:null"`
}

这就是我使用 GORM 更新记录的地方。为了减少这里的膨胀,我提取了一些验证代码、错误检查以及将请求正文读取到数据 MAP 中的代码。我认为这里的东西才是最重要的。

var person models.Person // account container
var pid uuid.UUID        // the person UUID

pid = uuid.MustParse(data["id"]) // Convert string to uuid

// Load existing person record based on the uuid/pid
if err := database.DB.Table("people").Select("*").Where("id = ?", pid).Scan(&person).Error; err != nil {
    if errors.Is(err, gorm.ErrRecordNotFound) {
        code := fiber.StatusNotFound
        return c.Status(code).JSON(fiber.Map{"Code": code, "Status": "Failed", "Message": "Person does not exist. Unable to update."})
    }
    code := fiber.StatusInternalServerError
    return c.Status(code).JSON(fiber.Map{"Code": code, "Status": "Failed", "Message": "An unknown error occurred during person record update."})
}
if _, ok := data["nameprefix"]; ok {
    person.NamePrefix = data["nameprefix"]
}
if _, ok := data["namefirst"]; ok {
    person.NameFirst = data["namefirst"]
}
if _, ok := data["namemiddle"]; ok {
    person.NameMiddle = data["namemiddle"]
}
if _, ok := data["namelast"]; ok {
    person.NameLast = data["namelast"]
}
if _, ok := data["namesuffix"]; ok {
    person.NameSuffix = data["namesuffix"]
}

// Save the updated person
if err := database.DB.Save(&person).Error; err != nil {
    code := fiber.StatusInternalServerError
    return c.Status(code).JSON(fiber.Map{"Code": code, "Status": "Failed", "Message": err})
}

这就是我与数据库的连接的配置方式。

func ConnectMySQL() {

    var DSNW1 string = os.Getenv("IL_APP_MYSQL_WRITE_DBUSER") + ":" + os.Getenv("IL_APP_MYSQL_WRITE_DBPASS") + "@tcp(" + os.Getenv("IL_APP_MYSQL_WRITE_HOST") + ":" + os.Getenv("IL_APP_MYSQL_WRITE_PORT") + ")/" + os.Getenv("IL_APP_MYSQL_WRITE_DBNAME") + "?parseTime=true"
    var DSNR1 string = os.Getenv("IL_APP_MYSQL_READ_DBUSER") + ":" + os.Getenv("IL_APP_MYSQL_READ_DBPASS") + "@tcp(" + os.Getenv("IL_APP_MYSQL_READ_HOST") + ":" + os.Getenv("IL_APP_MYSQL_READ_PORT") + ")/" + os.Getenv("IL_APP_MYSQL_READ_DBNAME") + "?parseTime=true"
    var datetimePrecision = 2

    connection, err := gorm.Open(mysql.New(mysql.Config{
        DSN:                      DSNW1,              // Primary writer instance
        DefaultStringSize:        256,                // add default size for string fields, by default, will use db type `longtext` for fields without size, not a primary key, no index defined and don't have default values
        DefaultDatetimePrecision: &datetimePrecision, // default datetime precision
    }))

    if err != nil {
        panic("Could not connect to the database.")
    }

    DB = connection

    DB.Use(dbresolver.Register(dbresolver.Config{
        Sources:  []gorm.Dialector{mysql.Open(DSNW1)}, // Writer(s)
        Replicas: []gorm.Dialector{mysql.Open(DSNR1)}, // Read replica(s)
        Policy:   dbresolver.RandomPolicy{},           // Load balancing policy
    }))

    connection.AutoMigrate(&models.Account{})
    connection.AutoMigrate(&models.Person{})
    connection.AutoMigrate(&models.PersonCredentials{})
    connection.AutoMigrate(&models.Client{})
    connection.AutoMigrate(&models.ClientCredentials{})

}

使用 GORM 更新记录后的示例表。

Example table after updating a record with GORM.

这是 GORM 应用的 SHOW CREATE TABLE 的结果。

CREATE TABLE `people` (
  `id` char(36) NOT NULL,
  `created_at` datetime(2) DEFAULT NULL,
  `updated_at` datetime(2) DEFAULT NULL,
  `deleted_at` datetime(2) DEFAULT NULL,
  `account_id` varchar(256) DEFAULT NULL,
  `name_prefix` varchar(256) DEFAULT NULL,
  `name_first` varchar(256) DEFAULT NULL,
  `name_middle` varchar(256) DEFAULT NULL,
  `name_last` varchar(256) DEFAULT NULL,
  `name_suffix` varchar(256) DEFAULT NULL,
  `notes` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_people_deleted_at` (`deleted_at`),
  KEY `idx_people_name_first` (`name_first`),
  KEY `idx_people_name_last` (`name_last`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

我错过了什么?谢谢

字符串 go null grails-orm

评论

2赞 spike014 7/26/2023
在 like 中使用 like 怎么样?*stringNamePrefix *stringPerson
0赞 wmc 7/26/2023
@spike014 - 这会导致编译器错误。
1赞 Branislav Lazic 7/26/2023
@wmc 当有一个空字符串时,GORM 无法解释你的意图,无论你是要传递一个空的 varchar,还是一个 null 值,除非 struct 属性可以是它本身。因此,您必须修复该编译时错误,或者具有空值。nil
0赞 wmc 7/28/2023
谢谢大家 - 这是有道理的。我是 Go 的新手,但开始掌握指针的窍门。

答: 暂无答案