Gorm框架后端实践|青训营

99 阅读5分钟
title: Gorm框架实践|青训营
categories: 青训营

实践选题: 使用 GORM(Go 的 ORM 库)连接数据库,并实现增删改查操作,把实现过程整理成文章;

1.准备工作

1.1 Gorm框架安装

使用Go自带的get进行安装,首先打开命令行(CMD或Shell),将路径切换至项目路径(go.mod所在路径),依次执行以下命令:

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

即可安装Gorm框架和Gorm的Mysql驱动,本文使用Mysql作为数据库,若使用其他数据库,请下载相应数据库驱动

1.2 DSN

Gorm框架的驱动使用DSN来连接数据库,因此需要配置DSN,DSN连接格式如下:

  • user:password@tcp(127.0.0.1:3306)/database_name?charset=utf8mb4&parseTime=True&loc=Local

分别是:用户名,密码,服务器地址(127.0.0.1),端口(3306),数据库名称等

首次配置方法(Windows):

  • 打开控制面板->管理工具->ODBC数据源->系统DSN
  • 添加MySQL ODBC 8.0 Driver
  • 设置数据源名称(随便命个名),TCP/IP 服务器地址(建议127.0.0.1:3306)
  • 输入用户名和密码,MySQL存在的用户,要有对应的表权限,若输入正确则可以选择下一列的数据库名称

对应的DSN为: root:123456@tcp(127.0.0.1:3306)/bloginfos?charset=utf8mb4&parseTime=True&loc=Local

2.连接

首先根据表结构创建对应的结构体来映射数据库表, 如下所示

则创建User结构体来映射user表,结构体名可以与表名不一致,但TableName方法返回值必须与表名一致,因为Gorm通过TableName获取表名来生成SQL语句

添加gorm.Model则会自动生成create_at,updated_atdeleted_at字段,这些字段也会在表中被创建

!!!注意:结构体中的属性名必须有且仅有首字母大写,否则无法被映射

// 创建结构体用于映射数据库表,字段名和类型与数据库表字段一致
type User struct {
    gorm.Model
    ID       int
    Username string
    Password string
    Isonline string
}
// 用于返回获取表名
func (p *User) TableName() string {
    return "User"
}

使用以下语句进行数据库连接并自动初始化

dsn := "root:123456@tcp(127.0.0.1:3306)/bloginfos?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }
    err = db.AutoMigrate(&User{})
    if err != nil {
        return
    }

3.查询

3.1 查询方式

Gorm提供三种方式来查询一条单一数据,分别是:

  • First查询第一条数据(主键递增的第一条数据)
  • Take查询一条数据,无顺序
  • Last查询最后一条数据(即主键递减的第一条数据)

Gorm通过Find来查询所有符合条件的元组

注意参数要传递引用,因为Gorm通过修改参数来返回结果,若不传递引用则无法得到结果

对于没有设置主键的表,则按第一个字段排序

这三种方法可以设置查询条件,如下所示,对于Find方法,查询到的所有结果会以数组的方式存储在uesr中

var user User
var users []User
db.First(&user)
db.Take(&user)
db.Last(&user)
db.Find(&users)

也可以不指定对象类别,适用表名来进行查询

result := map[string]interface{}{}
DB.Table("user").Take(&result)

将查询到的users表中的数据结果存储到result中

3.2 条件查询

Gorm有多种方法设置查询条件,此处以First为例,条件设置方式适用于其他查询方法

查询条件都以字符串形式出现,为查询字段+值的形式设置,其中查询字段为: 字段名+约束方法+?的形式组成,约束方法可以设置为SQL中的方法如=,>,<,between,in等

  • 主键查询:db.First(&user, 1)查询主键值为1的元组
  • 单一条件查询:db.First(&user, "username = ?", "admin")查询用户名为admin的元组
  • 多条件查询:db.First(&user, []string{"username = ?", "admin", "password = ?", "123456"})

除了上述查询条件的设置方法,还有以下几种:

  • db.Where("name = ?", "jinzhu").First(&user)
  • db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
  • db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)

也可以在一条字符串中设置多个查询条件,根据条件的数量依次读取后续参数作为查询值

  • db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)

4.插入

可以直接通过Create创建,未初始化的值将被作为空值传递

user = User{Username: "Jinzhu", Password: "123456", Isonline: "false"}
db.Create(&user)

批量插入

var users = []User{{Username: "jinzhu1"}, {Username: "jinzhu2"}, {Username: "jinzhu3"}}
DB.Create(&users)

5.更新

更新使用Update函数,可以与Where搭配使用,同时若传递参数为示例,则会自动将该示例的主键作为一个条件

//这里仅指定表名
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=user.id;

更新多个字段

db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = user.id;

使用select仅更新指定字段,即使参数中有多个字段数据

db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello' WHERE id=user.id;

6.删除

Gorm中提供了物理删除和软删除两种删除方法,物理删除将直接从数据库中删除该数据,而软删除会设置deleted_at字段而不会在数据库中删除,软删除后该条数据无法通过Gorm一般查询被查询到

6.1物理删除

若不指定条件,则按实例的主键作为条件删除对应数据,或与Where搭配使用

db.Delete(&user)
// DELETE from emails where id = user.id;
db.Where("name = ?", "jinzhu").Delete(&user)
// DELETE from emails where id = user.id AND name = "jinzhu";

不传递实例,按主键删除

db.Delete(&User{}, 1)
// DELETE FROM users WHERE id = 1;
db.Delete(&User{}, "1")
// DELETE FROM users WHERE id = 1;
db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);

批量删除,不传递实例

db.Where("username LIKE ?", "%jinzhu%").Delete(User{})
// DELETE from emails where email LIKE "%jinzhu%";
db.Delete(User{}, "username LIKE ?", "%jinzhu%")
// DELETE from emails where email LIKE "%jinzhu%";

6.2 软删除

若表中有gorm.DeletedAt字段,则该表可以使用软删除(该字段包含在gorm.Model中),软删除会被自动调用

软删除的原理是执行Update来为DeletedAt字段赋值为执行删除命令的时间

  • db.Delete(&user)// UPDATE users SET deleted_at=删除时间 WHERE id = user.id;

如果不想使用软删除,可以使用Uncoped执行下述命令

  • db.Unscoped().Delete(&order) // DELETE FROM orders WHERE id=10;

7.官方文档

更多详细内容可以参考Gorm官方文档

Gorm官方文档