Golang ORM类库:GORM的使用总结

Golang ORM类库:GORM的使用总结

技术概述

ORM(Object Relation Mapping 关系对象映射),就是把对象模型表示的对象映射到基于SQL的关系模型数据库结构中,在具体的操作实体对象的时候,不需要直接与复杂的 SQL语句打交道,只需简单的操作实体对象的属性和方法。而GORM就是基于Go语言实现的ORM库。在使用Go语言开发项目的时候,我们可以利用GORM来实现对数据库的操作,进行简单的CRUD操作。

技术详述

使用流程

使用GORM

1.导入GROM和数据库驱动

可以使用一下命令安装GROM和数据库驱动

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

但是这是一种比较传统的方法。我们还可以在项目中使用go.mod文件设置项目需要添加的依赖包:

go 1.15

require (
	gorm.io/driver/mysql v1.0.5
	gorm.io/gorm v1.21.8
)

像上面这样定义好需要添加的依赖包之后,就可以直接执行下面这一条指令让go.mod文件自动引入所有依赖包:

go mod download

执行完上述指令若没有任何反应则说明已经成功将GORM和数据库驱动的依赖包导入了

2.定义数据库连接信息

在项目中的.env文件中编写数据库连接的信息,可以大致按照如下格式编写,但需要根据具体项目要求修改具体信息,比如这里使用的数据库是MySQL的,如果使用的是其他数据库(PostgreSQL等),则需要修改MYSQL_DSN的内容:

MYSQL_DSN="root:12345678@tcp(localhost:3306)/pingleme?charset=utf8&parseTime=True&loc=Local"
REDIS_ADDR="pingleme.top:6379"
REDIS_PW="Test1234"
REDIS_DB=""
SESSION_SECRET="setOnProducation"
GIN_MODE="debug"
LOG_LEVEL="debug"
LOG_PATH="./.log/system.log"
LOG_MAX_SIZE="50"
LOG_MAX_AGE="30"
LOG_MAX_BACKUP="0"
LOG_COMPRESS="false"
LOG_JSON_FORMAT="false"
LOG_SHOW_LINES="true"
LOG_SHOW_IN_CONSOLE="true"
DB_LOG_LEVEL="info"

在这里可能会遇到一些连接问题,会在之后的“遇到的问题和解决过程”模块解释

3.获取数据库连接

完成以上准备工作后,需要先获取数据库的连接:

package main

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

func main() {
  db, err := gorm.Open("mysql", &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }
  defer db.Close()
  db.SingularTable(true)
}

4.定义数据库模型

GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。

定义数据库模型就是将数据库的表结构对应到struct中,比如如下的用户表表结构:

CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `uid` varchar(191) NOT NULL,
  `password_digest` longtext NOT NULL,
  `user_name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uid` (`uid`),
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

可以定义对应的struct:

// User 用户模型
type User struct {
	gorm.Model
	UID            string `gorm:"not null;unique"`
	PasswordDigest string `gorm:"not null"`
	UserName       string `gorm:"type:varchar(20);not null"`
}

struct的每个字段都对应着数据库表中的字段,而数据库字段的属性则由gorm声明的结构标记来定义。比如,"type:varchar(20)"定义了字段的类型与长度、"not null"则声明了字段是非空的,这些都与数据库中的声明一一对应。更多的属性定义可以查看官方文档给出的GORM模型定义

5.CRUD操作

5.1 创建
user := User{UID: "221801114", PasswordDigest: "123456", UserName: "silicon"}

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

user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数
5.2 查询
// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;

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

// 获取全部记录
result := db.Find(&users)
// SELECT * FROM users;

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

// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)
5.3 更新
db.First(&user)

user.PasswordDigest = "12345678"
db.Save(&user)
// UPDATE users SET uid='221801114', passworddigest="12345678", birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=1;
5.4 删除

删除记录时需要带主键,否则会导致批量删除:

// user 的 ID 是 `1`
db.Delete(&user)
// DELETE from users where id = 1;

// 带额外条件的删除
db.Where("uid = ?", "221801114").Delete(&user)
// DELETE from users where id = 1 AND uid = "221801114";

遇到的问题和解决过程

1. 数据库连接字符串出错

问题描述

当时配置数据库信息的时候没有按照规范书写连接串,导致数据库连接失败,错误代码如下:

MYSQL_DSN="root:12345678/pingleme?charset=utf8&parseTime=True&loc=Local"

解决

应当要将端口号等信息放在“@tcp()”的括号中,具体可以按照如下格式修改:

MYSQL_DSN="user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

2.数据库字段包含sql的关键字

问题描述

我在设计一个数据库表结构的时候,误将sql语句的关键字"index"作为数据库字段的名字:

CREATE TABLE `scoring_items` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `created_at` datetime(3) DEFAULT NULL,
  `updated_at` datetime(3) DEFAULT NULL,
  `deleted_at` datetime(3) DEFAULT NULL,
  `homework_id` bigint unsigned NOT NULL,
  `description` varchar(255) NOT NULL,
  `score` bigint NOT NULL DEFAULT '-1',
  `option` tinyint NOT NULL,
  `note` varchar(255) DEFAULT NULL,
  `assistant_id` bigint NOT NULL,
  `level` bigint NOT NULL DEFAULT '0',
  `index` bigint NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_scoring_items_deleted_at` (`deleted_at`),
  KEY `fk_homeworks_scoring_items` (`homework_id`),
  CONSTRAINT `fk_homeworks_scoring_items` FOREIGN KEY (`homework_id`) REFERENCES `homeworks` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

以致于我对这一个数据库表的如下查询操作屡次失败,找不出原因:

result = Repo.DB.Order("index desc").Where("homework_id = ?", ID).Find(&items)

解决

在使用该字段进行查询时,应该将该字段的名称包含在``之间,就可以避免与sql的冲突。比如,可以将上面的查询操作改为如下形式:

result = Repo.DB.Order("`index` desc").Where("homework_id = ?", ID).Find(&items)

总结

通过上述的介绍,就可以大致地使用GO提供的ORM类库GORM轻松的进行简单的CRUD操作了。学会了GORM,就不需要自己维护sql语句了。

参考文献

GORM指南

posted @ 2021-06-28 11:05  硅硅键  阅读(3135)  评论(2编辑  收藏  举报