Gorm 入门介绍与基本使用

Gorm 入门介绍与基本使用

Gorm 入门介绍与基本使用目录

Gorm 入门介绍与基本使用一、ORM简介1.1 什么是ORM1.2 使用ORM的好处1.2.1 避免直接操作SQL语句1.2.2 提高代码的可维护性1.2.3 跨数据库兼容性1.3 使用ORM的缺点1.3.1 学习成本1.3.2 性能开销1.4 ORM解析过程1.4.1 模型定义1.4.2 数据验证1.4.3 映射关系1.4.4 CRUD操作1.4.5 SQL生成与执行二、Gorm 介绍与安装2.1 介绍2.2 相关文档2.3 安装三、Gorm 连接数据库3.1 快速连接 MySQL3.2 MySQL数据库配置解析3.3 自定义 MySQL 驱动3.4 现有的数据库连接mysql3.5 切换数据库驱动3.6 编写新驱动3.7 连接PostgreSQL3.7.1 连接PostgreSQ举例3.7.2 连接PostgreSQL配置解析3.7.3 自定义 PostgreSQL 驱动3.7.4 现有的数据库连接PostgreSQL3.8 连接SQLite3.8.1 连接SQLite举例3.8.2 连接SQLite配置解析3.9 连接SQL Server3.9.1 连接SQL Server举例3.9.2 连接SQL Server配置解析3.10 连接TiDB3.10.1 连接TiDB举例3.10.2 连接TiDB配置解析3.10 连接Clickhouse3.10.1 连接Clickhouse举例3.10.2 连接Clickhouse配置解析四、连接池五、MySQL 其他配置六、加入日志打印sql6.1 打印日志6.2 日志级别6.3 Debug6.4 具体代码七、参考文档一、ORM简介1.1 什么是ORMORM(Object-Relational Mapping)是一种编程技术,它将对象和关系数据库之间的映射抽象出来,使得开发者可以通过面向对象的方式操作数据库,而不用直接处理SQL语句,相当于在业务逻辑层和数据库层之间一座桥梁。在Golang中,有一款优秀的ORM框架叫做Gorm,它提供了强大的功能,使得数据库操作变得更加简单和灵活。

1.2 使用ORM的好处使用ORM的好处主要包括:

1.2.1 避免直接操作SQL语句ORM框架可以屏蔽底层数据库的细节,开发者不需要编写复杂的SQL语句,从而降低了开发的难度。

1.2.2 提高代码的可维护性通过使用ORM,代码变得更加清晰、简洁,易于理解和维护。ORM框架通常提供了模型定义、数据验证等功能,使得开发者可以更专注于业务逻辑。

1.2.3 跨数据库兼容性ORM框架通常提供了对多种数据库的支持,开发者可以轻松切换数据库而无需修改大量代码。

1.3 使用ORM的缺点使用ORM也有一些缺点,主要包括:

1.3.1 学习成本学习使用ORM框架需要一定的时间,尤其是对于初学者来说,需要掌握框架的各种功能和用法。

1.3.2 性能开销ORM框架可能引入一些性能开销,尤其是在处理大量数据时。开发者需要在性能和开发效率之间做出权衡。

1.4 ORM解析过程ORM框架的解析过程包括以下步骤:

1.4.1 模型定义开发者需要定义数据模型,通常是一个结构体,表示数据库中的表结构。

1.4.2 数据验证ORM框架通常提供了数据验证的功能,确保数据的合法性和完整性。

1.4.3 映射关系ORM框架会建立数据模型与数据库表之间的映射关系,将结构体的字段与表的列进行对应。

1.4.4 CRUD操作开发者可以通过ORM框架进行CRUD(Create、Read、Update、Delete)操作,而不用直接编写SQL语句。

1.4.5 SQL生成与执行最终,ORM框架会根据开发者的操作生成相应的SQL语句,并执行在数据库中。

通过以上步骤,开发者可以使用ORM框架方便地进行数据库操作,提高开发效率。

在接下来的部分,我们将深入学习Gorm框架的使用,从入门到精通。

二、Gorm 介绍与安装2.1 介绍Gorm是一款用于Golang的ORM框架,它提供了丰富的功能,包括模型定义、数据验证、关联查询等。Gorm的设计目标是简洁而强大,使得开发者能够更轻松地进行数据库操作。

一些Gorm的特性包括:

模型定义和操作: 全功能 ORM关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)Create,Save,Update,Delete,Find 中的钩子方法支持 Preload、Joins 的预加载批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD复合主键,索引,约束事务处理和数据库操作: 事务,嵌套事务,Save Point,Rollback To Saved PointContext、预编译模式、DryRun 模式SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询Auto Migration其他功能: 自定义 Logger灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…每个特性都经过了测试的重重考验开发者友好最新版本2.x,比1.x有较大改动,注意:Gorm最新地址为https://github.com/go-gorm/gorm,之前https://github.com/jinzhu/gorm地址为v1旧版本

2.2 相关文档Gorm最新源码地址:https://github.com/go-gorm/gormV1版本地址:https://github.com/jinzhu/gorm中文文档地址:https://gorm.io/zh_CN/docs/2.3 安装要使用Gorm,首先需要安装它。可以使用Go的包管理工具go get进行安装:

代码语言:javascript代码运行次数:0运行复制# 安装gorm

go get -u gorm.io/gorm

# 如果要使用`mysql`, `GORM` 做了二次 封装,安装对应数据库的驱动

go get -u gorm.io/driver/mysql安装完成后,可以在项目中引入Gorm:

代码语言:javascript代码运行次数:0运行复制import "gorm.io/gorm"接下来,我们将学习如何连接数据库并开始使用Gorm。

三、Gorm 连接数据库3.1 快速连接 MySQL连接MySQL数据库是Gorm的常见用法。以下是一个简单的例子:

代码语言:javascript代码运行次数:0运行复制package main

import (

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

type Product struct {

gorm.Model

Code string

Price uint

}

func main() {

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

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

if err != nil {

panic("failed to connect database")

}

// 迁移 schema

db.AutoMigrate(&Product{})

// Create

db.Create(&Product{Code: "D42", Price: 100})

// Read

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(Product{Price: 200, Code: "F42"}) // 仅更新非零值字段

db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})

// Delete - 删除 product

db.Delete(&product, 1)

}请注意替换username、password和dbname为你自己的数据库信息。这里使用了MySQL数据库,你也可以根据需要选择其他数据库。

3.2 MySQL数据库配置解析代码语言:javascript代码运行次数:0运行复制dsn := "username:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"上述连接字符串(DSN)中的参数有:

username:password:数据库用户名和密码。tcp(localhost:3306):数据库地址和端口。/dbname:数据库名称。charset=utf8mb4:设置字符集为UTF-8。parseTime=True:启用时间解析。loc=Local:设置时区。你可以根据实际情况调整这些参数。

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

代码语言:javascript代码运行次数:0运行复制package main

import (

_ "example.com/my_mysql_driver"

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

func main() {

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

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

代码语言:javascript代码运行次数:0运行复制import (

"database/sql"

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

func main() {

sqlDB, err := sql.Open("mysql", "mydb_dsn")

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

Conn: sqlDB,

}), &gorm.Config{})

}3.5 切换数据库驱动Gorm支持多种数据库,你可以根据需要选择不同的数据库驱动。上面的例子中我们使用了MySQL的驱动,如果要连接其他数据库,只需更改导入的数据库驱动即可。

例如,如果要连接SQLite数据库,可以使用以下驱动:

代码语言:javascript代码运行次数:0运行复制import "gorm.io/driver/sqlite"然后在gorm.Open()中使用sqlite.Open()。

3.6 编写新驱动GORM 官方支持的数据库类型有:MySQL, PostgreSQL, SQLite, SQL Server 和 TiDB

有些数据库可能兼容 mysql、postgres 的方言,在这种情况下,你可以直接使用这些数据库的方言。

对于其它不兼容的情况,您可以自行编写一个新驱动,这需要实现 方言接口。

参考官网文档:【编写新驱动】

3.7 连接PostgreSQL3.7.1 连接PostgreSQ举例代码语言:javascript代码运行次数:0运行复制package main

import (

"gorm.io/driver/postgres"

"gorm.io/gorm"

)

type User struct {

gorm.Model

Name string

Age int

}

func main() {

dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"

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

if err != nil {

panic("failed to connect database")

}

defer db.DB()

// Migrate the schema

db.AutoMigrate(&User{})

}我们使用 pgx 作为 postgres 的 database/sql 驱动,默认情况下,它会启用 prepared statement 缓存,你可以这样禁用它:

代码语言:javascript代码运行次数:0运行复制// https://github.com/go-gorm/postgres

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

DSN: "user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai",

PreferSimpleProtocol: true, // disables implicit prepared statement usage

}), &gorm.Config{})3.7.2 连接PostgreSQL配置解析代码语言:javascript代码运行次数:0运行复制dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"上述示例中的 DSN 解析如下:

user=gorm:数据库用户名。password=gorm:数据库密码。dbname=gorm:数据库名称。port=9920:数据库连接端口。sslmode=disable:禁用 SSL 模式。TimeZone=Asia/Shanghai:设置时区。根据实际情况,你需要替换这些值为你的 PostgreSQL 数据库连接信息。

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

代码语言:javascript代码运行次数:0运行复制import (

_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"

"gorm.io/gorm"

)

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

DriverName: "cloudsqlpostgres",

DSN: "host=project:region:instance user=postgres dbname=postgres password=password sslmode=disable",

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

代码语言:javascript代码运行次数:0运行复制import (

"database/sql"

"gorm.io/driver/postgres"

"gorm.io/gorm"

)

sqlDB, err := sql.Open("pgx", "mydb_dsn")

gormDB, err := gorm.Open(postgres.New(postgres.Config{

Conn: sqlDB,

}), &gorm.Config{})3.8 连接SQLite3.8.1 连接SQLite举例代码语言:javascript代码运行次数:0运行复制package main

import (

"gorm.io/driver/sqlite"

"gorm.io/gorm"

)

type Product struct {

gorm.Model

Code string

Price uint

}

func main() {

dsn := "test.db" // SQLite数据库文件路径

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

if err != nil {

panic("failed to connect database")

}

defer db.DB()

// 迁移 schema

db.AutoMigrate(&Product{})

// 创建记录

db.Create(&Product{Code: "D42", Price: 100})

// 查询记录

var product Product

db.First(&product, 1)

db.First(&product, "code = ?", "D42")

// 更新记录

db.Model(&product).Update("Price", 200)

db.Model(&product).Updates(Product{Price: 200, Code: "F42"})

db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})

// 删除记录

db.Delete(&product, 1)

}3.8.2 连接SQLite配置解析代码语言:javascript代码运行次数:0运行复制dsn := "test.db"上述示例中的 test.db 是 SQLite 数据库文件的路径。你可以根据实际情况调整文件路径。

3.9 连接SQL Server3.9.1 连接SQL Server举例代码语言:javascript代码运行次数:0运行复制package main

import (

"gorm.io/driver/sqlserver"

"gorm.io/gorm"

)

type Product struct {

gorm.Model

Code string

Price uint

}

func main() {

dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"

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

if err != nil {

panic("failed to connect database")

}

defer db.DB()

// 迁移 schema

db.AutoMigrate(&Product{})

// 创建记录

db.Create(&Product{Code: "D42", Price: 100})

// 查询记录

var product Product

db.First(&product, 1)

db.First(&product, "code = ?", "D42")

// 更新记录

db.Model(&product).Update("Price", 200)

db.Model(&product).Updates(Product{Price: 200, Code: "F42"})

db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})

// 删除记录

db.Delete(&product, 1)

}3.9.2 连接SQL Server配置解析代码语言:javascript代码运行次数:0运行复制dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"上述示例中的 DSN 解析如下:

gorm:LoremIpsum86:用户名和密码。localhost:9930:数据库服务器地址和端口。database=gorm:数据库名称。3.10 连接TiDB3.10.1 连接TiDB举例iDB 兼容 MySQL 协议。 因此你可以按照 MySQL 一节来创建与 TiDB 的连接。

在使用 TiDB 时有一些值得注意的内容:

您可以在结构体中使用 gorm:"primaryKey;default:auto_random()" 标签从而调用 TiDB 的 AUTO_RANDOM 功能。TiDB supported SAVEPOINT from v6.2.0, please notice the version of TiDB when you use this feature.TiDB supported FOREIGN KEY from v6.6.0, please notice the version of TiDB when you use this feature.代码语言:javascript代码运行次数:0运行复制package main

import (

"fmt"

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

type Product struct {

ID uint `gorm:"primaryKey;default:auto_random()"`

Code string

Price uint

}

func main() {

dsn := "root:@tcp(127.0.0.1:4000)/test"

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

if err != nil {

panic("failed to connect database")

}

db.AutoMigrate(&Product{})

insertProduct := &Product{Code: "D42", Price: 100}

db.Create(insertProduct)

fmt.Printf("insert ID: %d, Code: %s, Price: %d\n",

insertProduct.ID, insertProduct.Code, insertProduct.Price)

readProduct := &Product{}

db.First(&readProduct, "code = ?", "D42") // find product with code D42

fmt.Printf("read ID: %d, Code: %s, Price: %d\n",

readProduct.ID, readProduct.Code, readProduct.Price)

}3.10.2 连接TiDB配置解析代码语言:javascript代码运行次数:0运行复制dsn := "root:@tcp(127.0.0.1:4000)/test"root: 数据库用户名。在这里,用户名是 "root"。@: 分隔用户名和密码的分隔符。"": 数据库密码。在这里,密码是空字符串,表示没有密码。tcp(127.0.0.1:4000): 数据库服务器的地址和端口。在这里,MySQL 服务器位于本地主机(127.0.0.1),端口是 4000。/test: 数据库名称。在这里,数据库名是 "test"。3.10 连接Clickhouse3.10.1 连接Clickhouse举例代码语言:javascript代码运行次数:0运行复制package main

import (

"gorm.io/driver/clickhouse"

"gorm.io/gorm"

)

type User struct {

gorm.Model

Name string

Age int

}

func main() {

dsn := "tcp://localhost:9000?database=gorm&username=gorm&password=gorm&read_timeout=10&write_timeout=20"

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

if err != nil {

panic("failed to connect database")

}

// 自动迁移 (这是GORM自动创建表的一种方式--译者注)

db.AutoMigrate(&User{})

// 设置表选项

db.Set("gorm:table_options", "ENGINE=Distributed(cluster, default, hits)").AutoMigrate(&User{})

// 插入

db.Create(&user)

// 查询

db.Find(&user, "id = ?", 10)

// 批量插入

var users = []User{user1, user2, user3}

db.Create(&users)

// ...

}3.10.2 连接Clickhouse配置解析代码语言:javascript代码运行次数:0运行复制dsn := "tcp://localhost:9000?database=gorm&username=gorm&password=gorm&read_timeout=10&write_timeout=20"上述示例中的 DSN 解析如下:

tcp://localhost:9000: ClickHouse 服务器的地址和端口。在这里,ClickHouse 服务器位于本地主机(localhost),端口是 9000。这是 ClickHouse 的默认端口。?: 连接参数的起始标志。database=gorm: 数据库名称。在这里,数据库名是 "gorm"。username=gorm: 数据库用户名。在这里,用户名是 "gorm"。password=gorm: 数据库密码。在这里,密码是 "gorm"。read_timeout=10: 读取超时时间。在这里,设置为 10 秒。write_timeout=20: 写入超时时间。在这里,设置为 20 秒。你需要根据实际情况替换这些值。

四、连接池GORM 使用 database/sql 来维护连接池

代码语言:javascript代码运行次数:0运行复制sqlDB, err := db.DB()

// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.

sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns sets the maximum number of open connections to the database.

sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.

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

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

代码语言:javascript代码运行次数:0运行复制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{})六、加入日志打印sql6.1 打印日志Gorm 有一个 默认 logger 实现,默认情况下,它会打印慢 SQL 和错误

Logger 接受的选项不多,您可以在初始化时自定义它,例如:

代码语言:javascript代码运行次数:0运行复制newLogger := logger.New(

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

logger.Config{

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

LogLevel: logger.Silent, // 日志级别

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

Colorful: false, // 禁用彩色打印

},

)

// 全局模式

db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{

Logger: newLogger,

})

// 新建会话模式

tx := db.Session(&Session{Logger: newLogger})

tx.First(&user)

tx.Model(&user).Update("Age", 18)6.2 日志级别GORM 定义了这些日志级别:Silent、Error、Warn、Info

代码语言:javascript代码运行次数:0运行复制db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{

Logger: logger.Default.LogMode(logger.Silent),

})6.3 DebugDebug 单个操作,将当前操作的 log 级别调整为 logger.Info

代码语言:javascript代码运行次数:0运行复制db.Debug().Where("name = ?", "jinzhu").First(&User{})6.4 具体代码代码语言:javascript代码运行次数:0运行复制package main

import (

"gorm.io/driver/mysql"

"gorm.io/gorm"

"gorm.io/gorm/logger"

"log"

"os"

"time"

)

type User struct {

ID int

}

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 官网文档: https://gorm.io/zh_CN/docs/models.html

相关资讯