GORM 是 Go 语言的一个强大的 ORM(对象关系映射)库,可以让开发者使用 Go 语言优雅地操作数据库。GORM是一个已经迭代了10年以上的功能强大的ORM框架,在字节内部被广泛使用并且拥有非常丰富的开源拓展。
本文将介绍如何使用 GORM 连接数据库并实现基本的增删改查操作,同时结合个人分析讨论其设计特点和使用感受。
使用GORM连接mysql数据库
定义GROM model
即定义表结构Product
,表中含有string
类型的Code
和uint
类型的Price
。
type Product struct {
Code string
Price uint
}
定义结构体时也可以使用default标签,为字段定义默认值
type User struct {
ID int64
Name string `gorm:"default: galeone"`
Age int64 `gorm:"default: 18"`
}
接下来为 model 定义表名,为Product
创建一个TableName()
方法返回一个内容为product
的string
,用于获取结构体的表名。
func (p Product) TableName() string {
return "product"
}
连接数据库
本文以连接mysql数据库为例。在连接mysql数据库之前,需要定义一个DSN,它是用于描述连接数据库所需信息的字符串。在使用 Go 的 go-sql-driver/mysql
驱动连接 MySQL 数据库时,DSN 是必须提供的参数,它包含了数据库的用户名、密码、地址、数据库名及其他可选配置项。
DSN 的基本格式如下:
[用户名]:[密码]@tcp([主机]:[端口])/[数据库名]?[参数列表]
连接数据库的代码
func main(){
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{})//&gorm.Config{}用于传递自定义配置
if err != nil{
panic("failed to connect database")
}
GORM连接数据库后的基本操作
1.创建数据
此处创建一条Code="D42", Price=100
的记录。除此之外,创建数据时还可以一次性创建多条数据,只不过创建一条数据时是传入一个变量,创建多条数据时是传入一个切片或数组。
// 创建数据
db. Create(&Product{Code: "D42", Price: 100})
如果创建记录时存在冲突的可能性,可以使用clause.OnConflict
处理冲突,下方给出一组在发生冲突时不进行任何处理的示例代码
p := &Product{Code: "D42", ID:1}
db.Clauses(clause.OnConflict{DoNothing: true}).Create(&p)
2.查询数据
首先通过var
声明一个product
变量,用来保存查询的结果。需要注意的地方是传入的变量必须是一个指针
,因为查询结果会返写到结构体中,这样才能保证结果能够写入到product
。查询方式可分为按主键查询和按条件查询。
// 查询数据
var product Product
//First只能查询一条记录
db.First(&product, 1) // 根据主键查询 ID 为 1 的记录
db.First(&product, "code = ?", "D42") // 根据字段值查询记录
使用First
时,需要注意查询不到数据时,会返回ErrRecordNotFound
,容易造成程序停止。而使用Find
查询多条数据,查询不到数据时,返回的是一个空数组,因此更多使用Find
查询。
var products []Product
result := db.Find(&products)//返回表中的所有记录
result := db.Where("price > ?", 100).Find(&products)//返回price大于100的所有记录
result := db.Where("price > ? AND code = ?", 100, "D42").Find(&products)//查询 `price > 100` 且 `code = "D42"` 的记录
3.修改数据
使用Model(&product)
指定需要更新的模型(product
表示数据库中的记录)。
更新一条记录时,使用Update("Price", 200)
来更新数据,第一个参数是字段名,第二个参数是要更新的值。
更新多条记录时,可以使用Struct更新,但使用Struct更新时,只会更新非零值,如果需要更新零值可以使用 Map 更新或使用Select 选择字段。
// Update - 将 product 的 price 更新为 200
db.Model(&product).Update("Price", value: 200)
// Update - 更新多个字段
db.Model(&product).Updates(Product{Price: 200,Code:"F42"})// 仅更新非零值字段
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
product := Product{Code: "D42", Price: 0} // Price 为零值
db.Model(&product).Select("Price").Updates(product)
另外使用 Table
方法可以直接指定表名进行数据更新,而不需要依赖模型结构体。这种方式常用于动态表名或者在没有定义模型结构体时操作数据库。
//如果没有 `Where`条件的更新会影响表中的所有记录,因此应谨慎使用。
db.Table("product").Where("Code = ?", D42).Update("price", 200)
4.删除数据
使用Delete
方法删除记录,指定要操作的模型&product
,指定删除的记录主键值1
。
// Delete - 删除 product
db.Delete(&product, 1)//从数据库中删除主键值为 `1` 的记录。
同样地Delete
方法也可以使用Where
条件,但是如果模型没有主键,GORM 无法自动生成 WHERE
条件,可能导致全部记录被删除。
db.Where("code = ?", "F42").Delete(&Product{})
需要注意的是,GORM内有几条默认的约定:
1.GORM默认使用名为ID的字段,作为主键
2.使用结构体的蛇形负数作为表名,字段名的蛇形作为列名
3.使用CreatedAt、UpdatedAt字段作为表的创建时间、更新时间
总结:GORM 是一个强大且灵活的 ORM 库,能够简化与数据库的交互。通过 GORM,可以方便地进行增、查、改、删等操作,同时支持更复杂的查询、事务处理以及数据冲突的处理。GORM 的自动迁移和多样化的操作方法使得开发者可以专注于业务逻辑,而不必过多关注数据库操作的细节。掌握 GORM 的常用操作和特性,可以有效提升开发效率,并保证代码的可维护性和扩展性。