Gorm框架学习--入门

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gorm框架学习--入门相关的知识,希望对你有一定的参考价值。

Gorm框架学习--入门


引言

前面,已经介绍了go标准库sqlx库操作mysql的教程,下面介绍专业的ORM框架Gorm来操作各类数据库。

本文内容摘抄自Gorm 2022-8月份官方文档教程,如果Gorm框架后续有更新,还是以最新版本的官方文档为准

  • 安装
go get -u gorm.io/gorm

根据操作的底层数据库不同,引入相关数据库驱动:

#操作mysql需要下载下面的依赖
go get -u gorm.io/driver/mysql
#操作sqllite需要下载下面的依赖
go get -u gorm.io/driver/sqlite
#其他版本数据库依赖可以自行查找
...

本文所有演示,均基于mysql,其余关系型数据库操作大同小异


快速入门

package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var MYSQL_ADDR ="user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

type Product struct 
	gorm.Model
	Code  string
	Price uint


//gorm.Model结构如下: 主要是提供一些通用字段
//type Model struct 
//	ID        uint `gorm:"primarykey"`
//	CreatedAt time.Time
//	UpdatedAt time.Time
//	DeletedAt DeletedAt `gorm:"index"`
//

func main() 
	//创建数据库连接
	db, err := gorm.Open(mysql.Open(MYSQL_ADDR), &gorm.Config)
	if err != nil 
		panic("failed to connect database")
	

	//根据实体对象创建对应的表结构
	db.AutoMigrate(&Product)

	//插入数据
	db.Create(&ProductCode: "D42", Price: 100)

	//查询数据
	var product Product
	db.First(&product, 1)                 // 根据整型主键查找
	db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录

	// Update - 将 product 的 price 更新为 200
	db.Model(&product).Update("Price", 200)
	// Update - 更新多个字段
	db.Model(&product).Updates(ProductPrice: 200, Code: "F42") // 仅更新非零值字段
	db.Model(&product).Updates(map[string]interface"Price": 200, "Code": "F42")

	// Delete - 删除 product---这里其实是隐式删除
	db.Delete(&product, 1)



模型定义

模型是标准的 struct,由 Go 的基本数据类型、实现了 ScannerValuer 接口的自定义类型及其指针或别名组成

例如:

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 已有的约定,可以减少您的配置和代码量。如果约定不符合您的需求,GORM 允许您自定义配置它们,这个后面再说。


gorm.Model

GORM 定义一个 gorm.Model 结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt

// gorm.Model 的定义
type Model struct 
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`

您可以将它嵌入到您的结构体中,以包含这几个字段,具体怎么嵌入,下面会说到。


高级选项

字段级权限控制

可导出的字段在使用 GORM 进行 CRUD 时拥有全部的权限,此外,GORM 允许您用标签控制字段级别的权限。这样您就可以让一个字段的权限是只读、只写、只创建、只更新或者被忽略

注意: 使用 GORM Migrator 创建表时,不会创建被忽略的字段

type User struct 
  Name string `gorm:"<-:create"` // allow read and create
  Name string `gorm:"<-:update"` // allow read and update
  Name string `gorm:"<-"`        // allow read and write (create and update)
  Name string `gorm:"<-:false"`  // allow read, disable write permission
  Name string `gorm:"->"`        // readonly (disable write permission unless it configured)
  Name string `gorm:"->;<-:create"` // allow read and create
  Name string `gorm:"->:false;<-:create"` // createonly (disabled read from db)
  Name string `gorm:"-"`            // ignore this field when write and read with struct
  Name string `gorm:"-:all"`        // ignore this field when write, read and migrate with struct
  Name string `gorm:"-:migration"`  // ignore this field when migrate with struct


创建/更新时间追踪(纳秒、毫秒、秒、Time)

GORM 约定使用 CreatedAtUpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充当前时间。

要使用不同名称的字段,您可以配置 autoCreateTimeautoUpdateTime 标签

如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可

type User struct 
  CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充
  UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充
  Updated   int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间
  Updated   int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间
  Created   int64 `gorm:"autoCreateTime"`      // 使用时间戳秒数填充创建时间


嵌入结构体

对于匿名字段,GORM 会将其字段包含在父结构体中,例如:

type User struct 
  gorm.Model
  Name string

// 等效于
type User struct 
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
  Name string

对于正常的结构体字段,你也可以通过标签 embedded 将其嵌入,例如:

type Author struct 
    Name  string
    Email string


type Blog struct 
  ID      int
  Author  Author `gorm:"embedded"`
  Upvotes int32

// 等效于
type Blog struct 
  ID    int64
  Name  string
  Email string
  Upvotes  int32

并且,您可以使用标签 embeddedPrefix 来为 db 中的字段名添加前缀,例如:

type Blog struct 
  ID      int
  Author  Author `gorm:"embedded;embeddedPrefix:author_"`
  Upvotes int32

// 等效于
type Blog struct 
  ID          int64
    AuthorName  string
    AuthorEmail string
  Upvotes     int32

如果根据Blog结构体来创建表,那么最终的表结构如下所示:


字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase 风格

golang中的tag类似java中注解的作用

标签名说明
column指定 db 列名
type列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not nullsize, autoIncrement… 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT
serializerspecifies serializer for how to serialize and deserialize data into db, e.g: serializer:json/gob/unixtime
sizespecifies column data size/length, e.g: size:256
primaryKeyspecifies column as primary key
uniquespecifies column as unique
defaultspecifies column default value
precisionspecifies column precision
scalespecifies column scale
not nullspecifies column as NOT NULL
autoIncrementspecifies column auto incrementable
autoIncrementIncrementauto increment step, controls the interval between successive column values
embeddedembed the field
embeddedPrefixcolumn name prefix for embedded fields
autoCreateTimetrack current time when creating, for int fields, it will track unix seconds, use value nano/milli to track unix nano/milli seconds, e.g: autoCreateTime:nano
autoUpdateTimetrack current time when creating/updating, for int fields, it will track unix seconds, use value nano/milli to track unix nano/milli seconds, e.g: autoUpdateTime:milli
indexcreate index with options, use same name for multiple fields creates composite indexes, refer Indexes for details
uniqueIndexsame as index, but create uniqued index
checkcreates check constraint, eg: check:age > 13, refer Constraints
<-set field’s write permission, <-:create create-only field, <-:update update-only field, <-:false no write permission, <- create and update permission
->set field’s read permission, ->:false no read permission
-ignore this field, - no read/write permission, -:migration no migrate permission, -:all no read/write/migrate permission
commentadd comment for field when migration

关联标签

GORM 允许通过标签为关联配置外键、约束、many2many 表,详情请参考关联部分


连接到数据库

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server

MySQL

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() 
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config)

注意: 想要正确的处理 time.Time ,您需要带上 parseTime 参数, (更多参数) 要支持完整的 UTF-8 编码,您需要将 charset=utf8 更改为 charset=utf8mb4 查看 此文章 获取详情

MySQL 驱动程序提供了 一些高级配置 可以在初始化过程中使用,例如:

db, err := gorm.Open(mysql.New(mysql.Config
  DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
  DefaultStringSize: 256, // string 类型字段的默认长度
  DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
  DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
  DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
  SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
), &gorm.Config)

自定义驱动

GORM 允许通过 DriverName 选项自定义 MySQL 驱动,例如:

import (
  _ "example.com/my_mysql_driver"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

db, err := gorm.Open(mysql.New(mysql.Config
  DriverName: "my_mysql_driver",
  DSN: "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local", // data source name, refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
), &gorm.Config)

现有的数据库连接

GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB

import (
  "database/sql"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

sqlDB, err := sql.Open("mysql", "mydb_dsn")
gormDB, err := gorm.Open(mysql.New(mysql.Config
  Conn: sqlDB,
), &gorm.Config)

其他

SQLite,SQL Server,Clickhouse,PostgreSQL相关数据库连接操作可以参考官方文档


连接池

GORM 使用 database/sql 维护连接池

sqlDB, err := db.DB()

// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)

查看 通用接口 获取详情。


参考

Gorm官网

以上是关于Gorm框架学习--入门的主要内容,如果未能解决你的问题,请参考以下文章

初学 go 入门-案例-教程-记录(13)orm 框架 Gorm 简单案例 - 连接sqlserver,并查询数据

GORM入门指南

Gorm框架学习---CRUD接口之查询

Golang之ORM框架Gorm快速开始

Golang之ORM框架Gorm快速开始

Golang之ORM框架Gorm快速开始