前言

前两篇笔记分别介绍了 Golang 微服务 HTTP 框架 Hertz 和 Golang 微服务 RPC 框架 Kitex,本文将要介绍面向ORM(持久层)框架 GORM。

官方文档

GORM 是面向 Golang 语言的一种 ORM(持久层)框架,支持多种数据库的接入,例如 MySQL,PostgreSQL,SQLite,SQL Server,Clickhouse。此框架的特点,弱化了开发者对于 SQL 语言的掌握程度,使用提供的 API 进行底层数据库的访问。

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

作者是中国人,中文文档齐全,对开发者友好,支持主流数据库。

特点:

全功能ORM;关联(包含一个,包含多个,属于,多对多,多种包含);Callbacks(创建/保存/更新/删除/查找之前/之后);预加载;事务复合主键SQL Builder自动迁移日志可扩展,编写基于GORM回调的插件每个功能都有测试开发人员友好

快速启动

安装与连接:

go get github.com/jinzhu/gorm

连接 MySQL 数据库:

package main

import (

"fmt"

"gorm.io/driver/mysql"

"gorm.io/gorm"

"time"

)

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{})

db, err := gorm.Open(mysql.New(mysql.Config{

DSN: "root:123456@tcp(192.168.168.101: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{})

if err != nil {

panic("failed to connect database")

}

// ----------------------------数据库连接池----------------------------

sqlDB, err := db.DB()

// SetMaxIdleConns 设置空闲连接池中连接的最大数量

sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns 设置打开数据库连接的最大数量。

sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime 设置了连接可复用的最大时间。

sqlDB.SetConnMaxLifetime(time.Hour)

fmt.Println("success to link mysql")

select {}

}

注意: 想要正确的处理 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, 详情参考: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{})

表数据操作:增删改查

package main

import (

"fmt"

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

type User struct {

Id int

Name string

Age int

Addr string

Pic string

}

func main() {

dsn := "root:root123\@tcp(127.0.0.1:3306)/test\_gorm?charset=utf8mb4\&parseTime=True\&loc=Local"

db, err := gorm.Open(mysql.Open(dsn), \&gorm.Config{})

if err != nil {

panic(err)

}

// 自动迁移

db.Set("gorm:table\_options", "ENGINE=InnoDB").AutoMigrate(\&User{})

// 增

db.Create(&User{

Name: "张三",

Age: 18,

Addr: "北京市",

Pic: "/static/img.png",

})

// 查

var user User

db.First(&user)

fmt.Println(user) // {1 张三 18 北京市 /static/img.png}

// 改

user.Name = "lisi"

db.Save(&user)

fmt.Println(user) // {1 lisi 18 北京市 /static/img.png}

// 删

db.Delete(&user)

}

模型定义:

模型名和表名的映射关系

规则:

第一个大写字母变为小写;遇到其他大写字母变为小写并且在前面加下划线;连着的几个大写字母,只有第一个遵循上面的两条规则,其他的大写字母转为小写,不加下划线,遇到小写,前面的第一个大写字母变小写并加下划线;复数形式;

举例:

User => users 首字母小写,复数UserInfo => user_infosDBUserInfo => db_user_infosDBXXXXUserInfo => dbxxxx_user_infos

结构体字段名和列名的对应规则

规则 * 列名是字段名的蛇形小写 举例

Name --> nameCreatedTime --> create_time 可以通过gorm标签指定列名,AnimalId int64 gorm:"column:beast_id"

gorm.Model

基本模型定义gorm.Model,包括字段 ID,CreatedAt,UpdatedAt,DeletedAt

参数说明:

ID:主键自增长;CreatedAt:用于存储记录的创建时间;UpdatedAt:用于存储记录的修改时间;DeletedAt:用于存储记录的删除时间;

只需要在自己的模型中指定gorm.Model匿名字段,即可使用上面的四个字段

gorm.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"`

}

// 添加字段 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`

type User struct {

gorm.Model

Name string

}

高级选项

结构体标签gorm的使用:

type User struct {

Name string `gorm:"<-:create"` // 允许读和创建

Name string `gorm:"<-:update"` // 允许读和更新

Name string `gorm:"<-"` // 允许读和写(创建和更新)

Name string `gorm:"<-:false"` // 允许读,禁止写

Name string `gorm:"->"` // 只读(除非有自定义配置,否则禁止写)

Name string `gorm:"->;<-:create"` // 允许读和写

Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)

Name string `gorm:"-"` // 读写操作均会忽略该字段

}

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

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

要使用不同名称的字段,您可以配置 autoCreateTim、autoUpdateTim 标签 如果您想要保存 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"` // 使用时间戳秒数填充创建时间

}

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase 风格,也就是驼峰 camelCase 命名风格。多个属性值之间用分号分隔(英文的;):gorm:"size:64;not null"

案例

package main

import (

"gorm.io/driver/mysql"

"gorm.io/gorm"

"gorm.io/gorm/logger"

"log"

"os"

"time"

)

type User struct {

UserId uint `gorm:"primaryKey"`

Name string `gorm:"column:user_name;type:varchar(60)"`

Gender uint `gorm:"index"`

}

func main() {

// 日志配置

newLogger := logger.New(

log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)

logger.Config{

SlowThreshold: time.Second, // 慢 SQL 阈值

LogLevel: logger.Info, // 日志级别为info

IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误

Colorful: true, // 彩色打印

},

)

dsn := "root:123@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{

Logger: newLogger,

})

if err != nil {

panic(err) // 如果数据库不存在会报错

}

db.AutoMigrate(&User{})

// 如果表之前存在会修改,但是只会修改之前存在的字段的属性,无法识别删除字段

}

总结

本文主要介绍了 GORM 框架的相关基础知识,介绍了常用的接口函数,具体的细节还是需要仔细研究官方文档。这三个框架的学习都可以看出官方文档的重要性,同时学习框架还是要多上手练习才行。

推荐阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: