文章目录
- [golang操作数据库ORM:GORM 包介绍及实战](#golang操作数据库ORM:GORM 包介绍及实战)
-
- [一、什么是GORM 包](#一、什么是GORM 包)
- 二、GORM基本使用
- [一些 GORM 提示和注意事项](#一些 GORM 提示和注意事项)
- 参考
golang操作数据库ORM:GORM 包介绍及实战
一、什么是GORM 包
github:https://github.com/go-gorm/gorm
官方文档:https://gorm.io/zh_CN/docs/index.html
GORM 是 Go 语言的 ORM 包,功能强大,调用方便。像腾讯、华为、阿里这样的大厂,都在使用 GORM 来构建企业级的应用。
- 全功能 ORM
- 关联 (拥有一个,拥有多个,属于,多对多,多态,单表继承)
- Create,Save,Update,Delete,Find 中钩子方法
- 支持 Preload、Joins 的预加载
- 事务,嵌套事务,Save Point,Rollback To to Saved Point
- Context、预编译模式、DryRun 模式
- 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
- SQL 构建器,Upsert,锁,Optimizer/Index/Comment Hint,命名参数,子查询
- 复合主键,索引,约束
- 自动迁移
- 自定义 Logger
- 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus...
- 每个特性都经过了测试的重重考验
- 开发者友好
二、GORM基本使用
官方快速开始demo
go
package main
import (
"gorm.io/gorm"
"gorm.io/driver/sqlite"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Migrate the schema
db.AutoMigrate(&Product{})
// Create
db.Create(&Product{Code: "D42", Price: 100})
// Read
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42
// Update - update product's price to 200
db.Model(&product).Update("Price", 200)
// Update - update multiple fields
db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // non-zero fields
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
// Delete - delete product
db.Delete(&product, 1)
}
db.AutoMigrate 意思 表不存在,会帮你创建表~
在 GORM 中,db.AutoMigrate(&Product{}) 函数只会在表不存在时执行数据库的自动迁移操作。如果指定的表已经存在于数据库中,并且与模型定义匹配,AutoMigrate 函数将不会对表结构进行任何更改。
- 连接和关闭数据库。连接数据库时,可能需要设置一些参数,比如最大连接数、最大空闲连接数、最大连接时长等。
- 插入表记录。可以插入一条记录,也可以批量插入记录。
- 更新表记录。可以更新某一个字段,也可以更新多个字段。
- 查看表记录。可以查看某一条记录,也可以查看符合条件的记录列表。
- 删除表记录。可以删除某一个记录,也可以批量删除。删除还支持永久删除和软删除。
使用思路:
0) 创建一个GORM数据库连接
GORM中,你可以使用gorm.Open()方法来打开数据库连接。根据你的数据库类型和连接配置,选择合适的数据库驱动。
go
db, err := gorm.Open("sqlite3", dbPath)
if err != nil {
ylog.Errorf("uploadFile", "open db failed, err:%v", err)
return
}
defer db.Close()
1) 定义与数据库表对应的模型结构体
首先定义了一个 GORM 模型(Models),Models 是标准的 Go struct,用来代表数据库中的一个表结构。我们可以给 Models 添加 TableName 方法,来告诉 GORM 该 Models 映射到数据库中的哪张表。
Models 定义如下:
go
type Product struct {
gorm.Model
Code string `gorm:"column:code"`
Price uint `gorm:"column:price"`
}
// TableName maps to mysql table name.
func (p *Product) TableName() string {
return "product"
}
如果没有指定表名,则 GORM 使用结构体名的蛇形复数作为表名。例如:结构体名为 DockerInstance ,则表名为 dockerInstances 。
- 解析命令行参数,建立数据库链接
在之后的代码中,使用 Pflag 来解析命令行的参数,通过命令行参数指定数据库的地址、用户名、密码和数据库名。之后,使用这些参数生成建立 MySQL 连接需要的配置文件,并调用 gorm.Open 建立数据库连接:
完整测试验证代码:
go
package main
import (
"fmt"
"log"
"github.com/spf13/pflag"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Product struct {
gorm.Model
Code string `gorm:"column:code"`
Price uint `gorm:"column:price"`
}
// TableName maps to mysql table name.
func (p *Product) TableName() string {
return "product"
}
var (
host = pflag.StringP("host", "H", "127.0.0.1:3306", "MySQL service host address")
username = pflag.StringP("username", "u", "root", "Username for access to mysql service")
password = pflag.StringP("password", "p", "root", "Password for access to mysql, should be used pair with password")
database = pflag.StringP("database", "d", "test", "Database name to use")
help = pflag.BoolP("help", "h", false, "Print this help message")
)
func main() {
// Parse command line flags
pflag.CommandLine.SortFlags = false
pflag.Usage = func() {
pflag.PrintDefaults()
}
pflag.Parse()
if *help {
pflag.Usage()
return
}
dns := fmt.Sprintf(`%s:%s@tcp(%s)/%s?charset=utf8&parseTime=%t&loc=%s`,
*username,
*password,
*host,
*database,
true,
"Local")
db, err := gorm.Open(mysql.Open(dns), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 不建议在正式的代码中自动迁移表结构,生产环境注意注掉本行
// 1. Auto migration for given models
db.AutoMigrate(&Product{})
// 2. Insert the value into database
if err := db.Create(&Product{Code: "D42", Price: 100}).Error; err != nil {
log.Fatalf("Create error: %v", err)
}
PrintProducts(db)
// 3. Find first record that match given conditions
product := &Product{}
if err := db.Where("code= ?", "D42").First(&product).Error; err != nil {
log.Fatalf("Get product error: %v", err)
}
// 4. Update value in database, if the value doesn't have primary key, will insert it
product.Price = 200
if err := db.Save(product).Error; err != nil {
log.Fatalf("Update product error: %v", err)
}
PrintProducts(db)
// 5. Delete value match given conditions
if err := db.Where("code = ?", "D42").Delete(&Product{}).Error; err != nil {
log.Fatalf("Delete product error: %v", err)
}
PrintProducts(db)
}
// List products
func PrintProducts(db *gorm.DB) {
products := make([]*Product, 0)
var count int64
d := db.Where("code like ?", "%D%").Offset(0).Limit(2).Order("id desc").Find(&products).Offset(-1).Limit(-1).Count(&count)
if d.Error != nil {
log.Fatalf("List products error: %v", d.Error)
}
log.Printf("totalcount: %d", count)
for _, product := range products {
log.Printf("\tcode: %s, price: %d\n", product.Code, product.Price)
}
}
一些 GORM 提示和注意事项
一些 GORM 提示和注意事项
参考URL: https://dev.to/daniel1in/some-gorm-tips-and-notes-3lm2
参考
官方文档:https://gorm.io/zh_CN/docs/index.html
30 | ORM:CURD 神器 GORM 包介绍及实战