使用 GORM(Go 的 ORM 库)连接数据库,并实现增删改查操作| 青训营

28 阅读4分钟

5.1 GORM

GORM(Go Object Relational Mapping)是一个在 Go 编程语言中使用的对象关系映射(ORM)库。ORM用于在关系型数据库和面向对象编程语言之间建立映射关系,使开发人员可以使用面向对象的方式操作数据库,而无需直接编写SQL查询语句。

连接MySQL:

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

一个连接MySQL以及建表的例子:

package main

import ( //导入 GORM 和 MySQL 数据驱动:
  "gorm.io/gorm"
  "gorm.io/driver/sqlite"
)

type Product struct { //定义gorm model
  gorm.Model
  Code  string
  Price uint
}

func (p product) TableName() string { //定义一个表名的接口
    return "product"
}

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{}) //连接数据库
  if err != nil {
    panic("failed to connect database")
  }

  // Migrate the schema 迁移
  db.AutoMigrate(&Product{})

  // Create 创建数据 可以传入切片,创建多条数据
  db.Create(&Product{Code: "D42", Price: 100})

  // Read 查询数据 First 单个查询
  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)
}

1、

type Product struct {
  gorm.Model
  Code  string
  Price uint
}

Product 结构体定义了一个数据模型,它将映射到数据库中的一个表。该结构体包含了 gorm.Model 字段,用于管理模型的基本属性,如 ID、创建时间、更新时间等。此外,还有 Code 和 Price 字段,分别表示产品的代码和价格。

2、

func (p Product) TableName() string {
    return "product"
}

函数是Product类型,返回string类型的参数;用于指定数据库中该模型对应的表名为 "product"。

3、

func main() {
  dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" 
  db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }

(1)dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" , 这行代码是一个连接数据库的 Data Source Name(DSN)字符串,用于配置和建立与数据库的连接。DSN 字符串包含了一系列参数,这些参数指定了连接的数据库类型、地址、认证信息、数据库名称以及其他一些连接选项。

不妨先贴出Mybatis plus中与数据库连接的代码:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/vueblog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis-plus:
  mapper-locations: classpath*:/mapper/**Mapper.xml

再重新看go中的代码:

  • user:pass: 这里代表数据库的用户名和密码。你需要将它们替换为实际的数据库用户名和密码。
  • tcp(127.0.0.1:3306): 这是数据库服务器的地址。127.0.0.1 表示本地主机,而 3306 是 MySQL 数据库的默认端口号。
  • /dbname: 这是要连接的数据库的名称。你需要将它替换为你要连接的实际数据库名称。
  • ?charset=utf8mb4: 这个参数指定了连接时要使用的字符集。utf8mb4 是一种支持更广泛字符集的 UTF-8 编码。
  • parseTime=True: 这个参数指示数据库驱动在从数据库读取时间类型字段时将其解析为 Go 的 time.Time 类型。
  • loc=Local: 这个参数设置了数据库使用本地时区。

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

在 main 函数中,使用 GORM 打开一个 SQLite 数据库连接。sqlite.Open("test.db") 指定数据库文件为 "test.db",并通过 &gorm.Config{} 使用默认的配置。

4、 db.AutoMigrate(&Product{}) AutoMigrate 方法用于自动迁移数据库模型,即根据模型结构自动创建对应的数据库表。在这里,它会创建一个名为 "product" 的表,该表对应于 Product 结构体。

db.Create(&Product{Code: "D42", Price: 100}) 使用 Create 方法向数据库中插入一条新的记录。

  var product Product
  db.First(&product, 1) // 根据主键查询
  db.First(&product, "code = ?", "D42") // 根据 code 字段查询

为什么需要定义 var product Product呢?我可以这样db.First(&Product,1)去查询吗?如果不可以的话,为什么前面db.Create(&Product{Code: "D42", Price: 100})可以使用&Product{}这个结构呢?

在 GORM 中,你需要定义一个变量来接收查询结果,因为查询结果需要被填充到这个变量中。这也是为什么你需要使用 var product Product 这样的语法来声明一个变量 product,并指定它的类型为 Product 结构体。

在 GORM 中,First 方法用于从数据库中查询记录并将结果填充到指定的模型实例中。具体来说,First 方法用于查询满足条件的第一条记录,并将查询结果赋值给提供的模型变量。

在 db.First(&Product, 1) 这种情况下,将 &Product 作为查询结果的接收变量是不合适的,因为 &Product 表示的是 Product 这个结构体类型,而不是结构体实例。查询结果需要被映射到一个实际的结构体实例中,所以需要使用类似 var product Product 的方式声明一个变量。

在 db.Create(&Product{Code: "D42", Price: 100}) 这里,使用 &Product{Code: "D42", Price: 100} 是可以的,因为这是在创建新的记录,你不需要先有一个实例来接收查询结果。这里的 &Product{Code: "D42", Price: 100} 创建了一个 Product 实例,然后通过 & 取得了该实例的指针,传递给了 db.Create 方法。