golang gorm 模型定义与tag字段详解

gorm

orm 概念

对象关系映射,可以通过操作实际数据结构,去操作具体的数据库表。减少一定工作量。更方便入手编程操作数据库, 减少一定SQL开发量

为什么使用orm

  • 规范一致,能调用的接口orm库提供
  • 减少一定工作量,建表,建库,修改表结构等(但一般生成环境都会直接指向对应ddl脚本),直接修改对象即可同步到数据库。
  • 对于一些开源系统,通用系统部署方便,只需要提供数据库
  • 解耦数据库和数据层,更加方便更换数据库引擎。

为什么不建议使用orm

  • 数据层不能因为使用orm而减少
  • 大量的反射,导致程序性能会比原生SQL慢(但不同orm库有对应优化。例如gorm采用预编译的机制,提前将一些对象字段的SQL编译好,生成SQL时直接通过缓存的方式查找出来,减少反射耗时)
  • orm提供了大量表关系接口,这些接口在数据流较少的情况时影响不大,当数据量大的时候是致命的
  • 没有SQL基础的开发,大概率不能正确使用orm

比如做表链接时,查询会很慢。一般是进行两次查询,然后业务内进行处理。(数据量大的时候绝大多数情况都会比直接一次表链接快)

PS: 表链接操作,不建议用orm(数据量少情况下也可以用)

gorm Model定义与tag使用

模型定义

使用标准的go struct。

go 复制代码
type User struct { 
    ID uint Name 
    string Email *string 
    Age uint8 Birthday *time.Time 
    MemberNumber sql.NullString 
    ActivatedAt sql.NullTime 
    CreatedAt time.Time 
    UpdatedAt time.Time 
}

GORM 倾向于约定优于配置 默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间如果遵循 GORM 的约定,可以少写的配置、代码。 如果约定不符合实际要求,则只能通过配置实现。

go Model
go 复制代码
package gorm

import "time"

// Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedAt, DeletedAt
// It may be embedded into your model or you may build your own model without it
//    type User struct {
//      gorm.Model
//    }
type Model struct {
	ID        uint `gorm:"primarykey"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt DeletedAt `gorm:"index"`
}

官方建议是直接内嵌到自己的结构体中

字段tag
tag desc
column 指定 db 列名
type 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes
serializer 指定序列化和反序列化方式,例如:json/gob/unixtime
size 指定列大小,例如:size:256
primaryKey 指定列为主键
unique 指定列为唯一
default 指定列的默认值
precision 指定列的宽度,例如:浮点数float(7,2),其中precision为7,表示不包括小数点在内的列宽,即整数部分加小数部分的总长度
scale 指定列中小数部分的宽度,例如:浮点数float(7,2),其中scale为2,表示浮点数的精度,多余的小数位数会被四舍五入
not null 指定列为 NOT NULL
autoIncrement 指定列为自动增长
autoIncrementIncrement 指定列的自增步长
embedded 嵌套字段
embeddedPrefix 嵌入字段的列名前缀
autoCreateTime 创建时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano
autoUpdateTime 创建/更新时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli
index 根据参数创建索引,多个字段使用相同的名称则创建复合索引
uniqueIndex 与 index 相同,但创建的是唯一索引
check 创建检查约束,例如 check:age > 13
<- 设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false无写入权限、<- 创建和更新权限
-> 设置字段读的权限,->:false 无读权限
- 忽略该字段,- 无读写权限
comment 添加字段描述信息
简单案例
go 复制代码
package _case

import "gorm.io/gorm"

func init() {
    DB.Migrator().AutoMigrate(Teacher{}, Course{})
}
type Roles []string

type Teacher struct {
    gorm.Model
    Name     string   `gorm:"size:256"`
    Email    string   `gorm:"size:256"`
    Salary   float64  `gorm:"scale:2;precision:7"`   // 指定小数部分宽度为2,列宽度为7. 列宽:【整数部分+小数部分的总长度】【不含小数点】
    Age      uint8    `gorm:"check:age>30"`
    Birthday int64    `gorm:"serializer:unixtime;type:time"`  // 反序列化方式 unixtime, 类型为time
    Roles    Roles    `gorm:"serializer:json"`
    JobInfo  Job      `gorm:"embedded;embeddedPrefix:job_"`   // 嵌套字段, 嵌入字段的列名前缀job_
    JobInfo2 Job      `gorm:"type:bytes;serializer:gob"`      // 字节流类型,gob反序列化,go自己的序列化方法,跨语言项目的时候,不建议用
}

type Job struct {
    Title    string
    Location string
}

type Course struct {
    gorm.Model
    Name   string  `gorm:"size:256"`
    Price  float64 `gorm:"scale:2;precision:7"`
    UserID uint    `gorm:"type:int"`
}
应用建议

实际生产中,基本上都是用ddl脚本去建数据库,或者用一些数据迁移框架去移植表(配合ddl脚本) 很少用gorm去做ddl操作,都是仅用来做增删改查事务 等非ddl操作。

相关推荐
意倾城8 分钟前
Spring Boot 配置文件敏感信息加密:Jasypt 实战
java·spring boot·后端
火皇4058 分钟前
Spring Boot 使用 OSHI 实现系统运行状态监控接口
java·spring boot·后端
rylshe131427 分钟前
在scala中sparkSQL连接mysql并添加新数据
开发语言·mysql·scala
小宋加油啊27 分钟前
Mac QT水平布局和垂直布局
开发语言·qt·macos
薯条不要番茄酱40 分钟前
【SpringBoot】从零开始全面解析Spring MVC (一)
java·spring boot·后端
MyhEhud1 小时前
kotlin @JvmStatic注解的作用和使用场景
开发语言·python·kotlin
想睡hhh1 小时前
c++进阶——哈希表的实现
开发语言·数据结构·c++·散列表·哈希
Clown951 小时前
Go语言爬虫系列教程(一) 爬虫基础入门
开发语言·爬虫·golang
Watermelo6171 小时前
前端如何应对精确数字运算?用BigNumber.js解决JavaScript原生Number类型在处理大数或高精度计算时的局限性
开发语言·前端·javascript·vue.js·前端框架·vue·es6
Aric_Jones3 小时前
lua入门语法,包含安装,注释,变量,循环等
java·开发语言·git·elasticsearch·junit·lua