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

71 阅读3分钟

Gorm 框架

安装

go get -u gorm.io/gorm

go get -u gorm.io/driver/sqlite

模型定义

type Student struct {
  Id	     int	`gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` //column指定在数据库中对应的字段
  Name         string 	`gorm:"column:name" json:"name"`
  Sex          string	`gorm:"column:sex" json:"sex"`
  Age          string	`gorm:"column:age" json:"age"`
}

GORM 倾向于约定优于配置:

  • 默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间
  • gorm提供了一个gorm.Model结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt,我们可以直接把它嵌入我们的结构体
  • 我们可以使用tag来控制字段,详见官方文档
  • 需要注意的是,在gorm中,表名默认是结构体名的复数,列名默认是字段名的蛇形小写。比如上述结构体,gorm会认为表名是studnets,那如何解决这个问题呢?只需要在init的时候加一句db.SingularTable(true)或者在查询时临时指定表名

连接到数据库

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

连接到MySQL:

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "student:pass@tcp(127.0.0.1:3306)/school?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}

GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB,例如:

import (
  "database/sql"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

var db *gorm.DB

func initDB() {
	var err error
	dsn := "student:pass@tcp(127.0.0.1:3306)/school?charset=utf8mb4&parseTime=True&loc=Local"
	//dsn := dsn.DSN 
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Println(err)
	}
    db.SingularTable(true)
	log.Println("connect success:")
}

在使用ORM工具时,通常我们需要在代码中定义模型(Models)与数据库中的数据表进行映射,在GORM中模型(Models)通常是正常定义的结构体、基本的go类型或它们的指针。 同时也支持sql.Scanner及driver.Valuer接口(interfaces)。

为了方便模型定义,GORM内置了一个gorm.Model结构体。gorm.Model是一个包含了ID, CreatedAt, UpdatedAt, DeletedAt四个字段的Golang结构体。

插入

CreatedAt

如果模型有 CreatedAt字段,该字段的值将会是初次创建记录的时间。

user := User{Name: "Jinzhu", Age: 18}

result := db.Create(&user) // 通过数据的指针来创建

//当然也支持创建多条信息(传递一个`slice`给`Create`函数),分批创建(`CreateInBatches()`)

查询

db.Model("所使用的表对应的结构体").Where("你的条件").Find("结果储存的位置的地址")
// 获取第一条记录(主键升序)
db.First(&user)

// 获取一条记录,没有指定排序字段
db.Take(&user)

// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error        // returns error or nil

// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)

更新

UpdatedAt

如果模型有UpdatedAt字段,该字段的值将会是每次更新记录的时间。

// save会储存所有的字段-即使字段是零值
db.Save(&user)

// 条件更新
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")

// User 的 ID 是 `111`
db.Model(&user).Update("name", "hello")

// 根据条件和 model 的值进行更新
db.Model(&user).Where("active = ?", true).Update("name", "hello")

删除

DeletedAt

如果模型有DeletedAt字段,调用Delete删除该记录时,将会设置DeletedAt字段为当前时间,而不是直接将记录从数据库中删除。

// Email 的 ID 是 `10`
db.Delete(&email)
// DELETE from emails where id = 10;

// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)