Gorm(Postgres)自定义类型主键无法设置自增?

前提:

  1. gorm.io/gorm v1.25.1
  2. gorm.io/driver/postgres v1.5.0

原因,主键在表自动迁移时无法创建自增。

附代码如下,之所以给主键设置为自定义类型,主要是考虑了bigint在前端可能会丢失精度的问题。现在别的都正常,就是自动创建表时,不会设置为自增。

type GVA_MODEL struct {
  ID BigInt `gorm:"primaryKey;autoIncrement:true;type:bigint;size:64;->" form:"id" json:"id" query:"id"` // 主键ID
  // ...
}
// 自定义类型,让客户端以string形式处理BigInt类型的数据
type BigInt json.Number
// Scan 实现 sql.Scanner 接口,Scan 将 value 扫描至 BigInt
func (bigint *BigInt) Scan(value interface{}) error {
  bytes, ok := value.(int64)
  if !ok {
    return errors.New(fmt.Sprint("Failed to unmarshal Int64 value:", value))
  }

  var result = json.Number(strconv.FormatInt(bytes, 10))
  *bigint = BigInt(result)
  return nil
}

// Value 实现 driver.Valuer 接口,Value 返回 BigInt value
func (bigint BigInt) Value() (driver.Value, error) {
  if len(bigint) == 0 {
    return nil, nil
  }
  return json.Number(bigint).Int64()
}

func (BigInt) GormDBDataType(db *gorm.DB, field *schema.Field) string {
  // 根据不同的数据库驱动返回不同的数据类型
  switch db.Dialector.Name() {
  case "mysql", "sqlite":
    return "bigint"
  case "postgres":
    if field.AutoIncrement { // 这是已修复后的
        return "bigserial"
    }
    return "bigint"
  }
  return "bigint"
}
阅读 3.9k
2 个回答

通过调试 gorm和driver/postgres的代码,已经搞定了,即在GormDBDataType判断字段是否自增,如果是自增,则返回bigserial

func (bigint BigInt) GormDBDataType(db *gorm.DB, field *schema.Field) string {
    // 根据不同的数据库驱动返回不同的数据类型
    switch db.Dialector.Name() {
    case "mysql", "sqlite":
        return "bigint"
    case "postgres":
        if field.AutoIncrement {
            return "bigserial"
        }
        return "bigint"
    }
    return "bigint"
}

PS:如果字段对应类型实现了GormDBDataType接口,则在表创建时,直接以GormDBDataType返回的类型创建表的字段。

为什么不直接用 int64 ? 要自己写 json.Number ?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题