如何防止 gorm 将自定义整数类型转换为字符串?

问题描述

我在使用具有整数属性自定义类型的 gorm 时遇到了麻烦。 Gorm 倾向于为我将整数值转换为字符串。有两个不同的问题:

问题 1:

我有一个自定义类型,定义如下:

type ClientType uint8

const (
    USER ClientType = iota
    SERVER
)

func (t ClientType) String() string {
    return [...]string{"User","Service"}[t]

然后我有一个 Client 的 ORM 结构,定义如下:

type Client struct {
    ClientID uint64 `gorm:"primaryKey"`
    UserID uint64
    ClientType ClientType
    CreatedAt time.Time
}

调用 db.Create(&client) 时,gorm 自动调用 String() 上的 ClientType 方法,并导致 MysqL 中的数据类型不匹配,我打算将 ClientType 存储在 {{ 1}} 列名为 tinyint

问题 2:

所以我想如果我无法弄清楚如何覆盖 client_type 方法自动调用,我只是将该方法重命名String() 并在需要时调用它。现在 gorm 不能再调用它了,而是将整数值转换为数字字符串。所以 ToString()USER,现在在结果 sql 语句中将变为 0,而 '0' 将变为 SERVER,尽管 MysqL 能够转换字符串回到整数。

我仍然想知道我做错了什么让 gorm 认为我想要这些转换。

  1. 有没有办法覆盖 '1'调用,所以我仍然可以按惯例命名方法
  2. 是否使用 String() 使 gorm 将 int 转换为字符串,因为使用 uint64 的其他数值(ClientID 和 UserID)不受此问题的影响?是某种 DB 模式的缓存让 gorm 记住了 client_type 曾经是 uint8 列的旧模式吗?

解决方法

根据需要实现自定义类型的 gorm Value and Scan

您也可以尝试在 struct 中指定类型(将 替换为列类型)。

type Client struct {
    ClientID   uint64 `gorm:"primaryKey"`
    UserID     uint8
    ClientType ClientType `gorm:"type:<TYPE>"`
    CreatedAt  time.Time
}

String() 似乎不是问题,因为它不会在创建过程中调用,而只会在查找过程中调用。

使用 db.LogMode(true),它也在创建过程中被调用,但这似乎是用于 sql 查询日志记录而不是发送到数据库。

关闭日志模式

    db.LogMode(false)
    fmt.Println("Creating")
    db.Create(&Client{ClientID: 9,UserID: 8,ClientType: USER,CreatedAt: time.Now()})
    fmt.Println("Created")

    fmt.Println("Finding")
    db.First(&client)
    fmt.Printf("Found %v\n",client)

输出

Creating
Created
Finding
String() called with 0
Found {9 8 User 2021-01-28 11:41:51.355633057 +0530 +0530}

启用登录模式

    db.LogMode(true)
    fmt.Println("Creating")
    db.Create(&Client{ClientID: 9,client)

输出:

Creating
String() called with 0
[2021-01-28 11:39:30]  [0.95ms]  INSERT INTO "clients" ("client_id","user_id","client_type","created_at") VALUES (9,8,'User','2021-01-28 11:39:30')  
[1 rows affected or returned ] 
Created
Finding
[2021-01-28 11:39:30]  [1.49ms]  SELECT * FROM "clients"   LIMIT 1  
[1 rows affected or returned ] 
String() called with 0
Found {9 8 User 2021-01-28 11:42:31.245628274 +0530 +0530}