当前位置: 首页 > article >正文

【Gorm】自定义数据类型

       很多情况下,我们有存JSON的需求,那么就需要使用到gorm中的自定义数据类型了。自定义的数据类型必须实现 Scanner 和 Valuer 接口,简单地说,在入库的时候转换一下,变成普通字符串记性存储,查询的时候,映射为结构体。

一、JSON 自定义数据类型

       JSON数据用的比较多,我们在迁移数据库之前,我们需要先对自定义数据类型进行接口函数的重新定义,只需要定义 Scanner 和 Valuer 函数即可,否则会迁移数据库失败。下面,我们来看一看代码是什么??

type Info struct {
    Like []string `json:"like"`
    Addr string `json:"addr"`
    Age int `json:"age"`
}

// Scan 实现 sql.Scanner 接口, Scan 将 value 扫描到 Jsonb
func (j *Info) Scan(value interface{}) error {
    bytes, ok := value.([]byte)
    if !ok {
        return errors.New(fmt.Sprintf("Failed to unmarshal JSONB value:", value))
    }

    result := Info{}
    err := json.Unmarshal(bytes, &result)
    *j = result
    return err
}

// value 实现 driver.Valuer 接口, Value 返回 json value
func (j Info) Value() (driver.Value, error) {
    return json.Marshal(j)
}

注意:这里千万不要自作聪明,去改指针方法或者接受者方法,Scan是指针方法,Value是接收者方法。

1.1 插入数据

我们可以使用 create 方法去插入数据,代码如下:

type User struct {
    ID int64
    Name string `gorm:"size:32"`
    Info Info `gorm:"type:longtext" json:"info"`
}

DB.Create(&User{
  Name: "加油旭杏",
  Info: Info{
    Age:  20,
    Addr: "湖北武汉",
    Like: []string{"唱", "跳", "rap"},
  },
})

1.2 查询数据

var user User

DB.Take(&user, 1)
fmt.Println(user.Name, user.Info.Like)

二、序列化

       如果只是存储 json 数据,完全可以使用 gorm 的序列化,自带 json,我们的自定义类型不需要写上述的两个函数接口,只需要在建立数据库的结构体的字段后添加一个字段即可:`gorm:"serializer:json"`,代码如下:

type User struct {
  ID   int64
  Name string `gorm:"size:32"`
  Info Info   `gorm:"type:longtext;serializer:json" json:"info"`
}

三、枚举类型

       有些情况下,在数据库里面需要存储一些标识状态的内容,比如描述日志的等级,通常有固定的几个值,比如:info,waring,error等,如果直接存储字符串,很明显是浪费空间,所以可以使用自定义类型。枚举类型不需要进行编写两个函数接口,就可以迁移数据库。代码如下:

type Status int8

const (
  Running Status = 1
  Warning Status = 2
)

type User struct {
  ID     int64
  Name   string `gorm:"size:32"`
  Status Status `json:"status"`
}

       因为返回前端的时候,肯定是会走json序列化的,所以返回给前端的时候就是对应的中文,我们可以实现一个函数,代码如下:

func (s Status) MarshalJSON() (data []byte, err error) {
  var str string
  switch s {
  case Running:
    str = "运行中"
  case Warning:
    str = "警告"
  }
  return json.Marshal(str)
}

       不过这个函数可以再优化一下,只返回中文的数据是比较少的,还需要把他本身的数字也返回出来,我们可以使用map来进行操作,代码如下:

func (s Status) MarshalJSON() (data []byte, err error) {
  var str string
  switch s {
  case Running:
    str = "运行中"
  case Warning:
    str = "警告"
  }
  return json.Marshal(map[string]any{
    "status":      int8(s),
    "statusTitle": str,
  })
}


http://www.kler.cn/a/372605.html

相关文章:

  • 哪个牌子的宠物空气净化器好?口碑好的宠物空气净化器推荐!
  • 【OpenSearch】机器学习(Machine Learning)神经搜索教程
  • Linux线程安全(二)条件变量实现线程同步
  • 一、在cubemx下RTC配置调试实例测试
  • 前端面试题(实习版)
  • 【网页布局技术】项目五 使用CSS设置导航栏
  • MacOS的powermetrics命令查看macbook笔记本的耗能情况,附带查看ANE的工作情况
  • 基于单片机的恒流源技术研究
  • ADS8320E/2K5 数据手册ADS8320一款16位模数转换器 A/D转换器芯片
  • IDEA连接数据库报错(javax.net.ssl.SSLHandshakeException: No appropriate protocol )
  • 使用openssl验证https配置的ssl证书是否可以正常访问
  • CentOS 9 Stream 上安装 Git
  • 分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB)
  • AutoDIR: Automatic All-in-One Image Restoration with Latent Diffusion论文阅读笔记
  • Efficient Cascaded Multiscale Adaptive Network for Image Restoration 论文阅读笔记
  • pip install -e .将正在开发的python包安装到虚拟环境中,以便测试和调试。 如果该包有依赖项,pip会自动安装依赖项
  • Mongodb使用视图连接两个集合
  • BackTrader -Indicators 03
  • electron+vite+ts+vue3
  • P8775 [蓝桥杯 2022 省 A] 青蛙过河
  • CUDA环境安装终极指南——Linux(其它系统也一样)
  • 订购 Claude AI 的第二天 它独自完成 文字转语音 flask应用
  • C++ | Leetcode C++题解之第519题随机翻转矩阵
  • 轻型民用无人驾驶航空器安全操控理论培训知识总结-多旋翼部分
  • Redis 下载安装(Windows11)
  • 算法刷题基础知识总结