一篇文章简单了解gorm框架

一篇文章简单了解gorm框架

什么是ORM

所谓ORM即是 Object Relational Mapping:对象关系映射,也就是说结构体 和 SQL数据库存在映射,这个时候就有了ORM语句

也就是说所谓ORM就是建立数据库中表数据与代码中结构体建立的关系

什么是gorm框架

gorm官方中文文档地址

GORM(Go Object Relational Mapping)是一个基于 Go 语言的 ORM 框架,用于简化数据访问和持久化的过程。它提供了一种简单、灵活和强大的方式来管理数据库,同时也支持多种数据库,如 MySQL、PostgreSQL、SQLite、SQL Server 等。

GORM 提供了一组易于使用的 API,可以通过结构体和标签来定义数据库表和字段,从而实现数据库的 CRUD 操作。它还支持事务、预加载、联表查询、分页查询、软删除、自动迁移和钩子等功能,以满足各种应用程序的需求。gorm是一个使用Go语言编写的ORM框架。它文档齐全,对开发者友好,支持主流数据库。

安装gorm

bash 复制代码
go get -u gorm.io/gorm 
go get -u gorm.io/driver/sqlite 

连接数据库(以mysql为例子)

go 复制代码
package main  
  
import (  
    "fmt"  
    "gorm.io/driver/mysql"  
    "gorm.io/gorm"  
    "gorm.io/gorm/schema"  
    "time"  
)  

  
func main() {  
  
//dsn就是指定了数据库的一些配置,比如说访问数据库的用户,密码,以及库的名字编码方式等  
    dsn := "root:3356@tcp(127.0.0.1:3306)/minitok?charset=utf8mb4&parseTime=True&loc=Local"  
    db, err := gorm.Open(mysql.New(mysql.Config{  
        DSN: dsn, // DSN data source name//最为关键的一步,配置DSN  
        DefaultStringSize: 256, // string 类型字段的默认长度  
        DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持  
        DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引  
        DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列  
        SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置  
     }), &gorm.Config{  
        SkipDefaultTransaction: false,  
        NamingStrategy: schema.NamingStrategy{  
        TablePrefix: "t_",  
        SingularTable: false,  
    },  
    DisableForeignKeyConstraintWhenMigrating: true,  
})  

fmt.Println(db, err)  
  
}

实际上通过gorm连接数据库是十分简单的,最核心的一步是正确的配置DSN即可

在 GORM 中,DSN(Data Source Name)是一种用于连接数据库的字符串格式,包含了连接数据库所需的参数和信息。DSN 格式的具体内容会根据不同的数据库类型而有所不同,但通常包括以下信息:

  • 数据库类型(如 MySQL、PostgreSQL、SQLite、SQL Server 等)
  • 数据库用户名和密码
  • 数据库地址和端口号
  • 数据库名称
  • 其他连接选项(如 SSL 选项等)

在 GORM 中,通过在 Open() 方法中传递 DSN 字符串,可以打开一个数据库连接。例如,在连接到 MySQL 数据库时,可以使用以下 DSN 格式:

go 复制代码
"username:password@tcp(host:port)/database?charset=utf8&parseTime=True&loc=Local"

其中,usernamepassword 分别为数据库的用户名和密码,hostport 分别为数据库的地址和端口号,database 为要连接的数据库名称。charset=utf8 表示使用 UTF-8 编码,parseTime=True 表示自动解析时间类型,loc=Local 表示使用本地时区。

在实际使用中,可以根据具体的数据库类型和需求来设置不同的 DSN 字符串。GORM 支持多种数据库,因此可以在不同的应用场景中灵活切换和使用。

此外,gorm定义了许多操作数据库的接口,比如db.create(&User{})...等,可以自行查阅官方文档自行进行上手实践。

创建数据库:

在我们使用GROM之前我们应该先创建好相应的数据库

sql 复制代码
CREATE DATABASE db1

然后再使用GORM连接操作数据库

go 复制代码
package main
​
import (
    "fmt"  
    "gorm.io/driver/mysql"  
    "gorm.io/gorm"  
    "gorm.io/gorm/schema"  
    "time"
)
​
// UserInfo 用户信息
type UserInfo struct {
    ID uint
    Name string
    Gender string
    Hobby string
}
​
​
func main() {
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    //DSN需要根据自己的配置进行更改
    if err!= nil{
        panic(err)
    }
    defer db.Close()
​
    // 自动迁移
    db.AutoMigrate(&UserInfo{})
​
    u1 := UserInfo{2023, "Nanami", "女", "游戏"}
    u2 := UserInfo{2024, "Sakana", "女", "游泳"}
    // 创建记录
    db.Create(&u1)
    db.Create(&u2)
    // 查询
    var u = new(UserInfo)
    db.First(u)
    fmt.Printf("%#v\n", u)
​
    var uu UserInfo
    db.Find(&uu, "hobby=?", "足球")
    fmt.Printf("%#v\n", uu)
​
    // 更新
    db.Model(&u).Update("hobby", "双色球")
    // 删除
    db.Delete(&u)
}

上述代码简单的演示了从连接数据库到对数据库进行简单的增删改查操作的过程;

更多的例子请查阅官方文档.

GORM Model定义

在使用ORM框架的时候,我们通常需要在代码中定义模型即Model来与数据库中的表单进行映射 ,在GORM框架中Models通常是正常定义的结构体、基本的go类型或者它们的指针。

为了使定义数据库表单更加规范,GORM内置了一个gorm.Model结构体。他的定义如下:

go 复制代码
// gorm.Model 定义
type Model struct {
  ID        uint `gorm:"primary_key"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt *time.Time
}

你可以把gorm.Model匿名嵌入到自己的结构体之中

go 复制代码
type BasicInfo struct {  
    Time time.Time `gorm:"column:basic_time"`  
    Basic_sentence string `gorm:"primaryKey"`  
}  
  
type User struct {  
    gorm.Model  
    infos BasicInfo `gorm:"embedded;embeddedPrefix:em_"`  
    Nickname string  
    Email *string  
    Age uint8  
}

在调用db.AutoMigrate{&User{}}之后再查询数据库之中的表单可以看到一下结果是符合我们预期的。

sql 复制代码
mysql> describe t_users;
+----------------+---------------------+------+-----+---------+----------------+
| Field          | Type                | Null | Key | Default | Extra          |
+----------------+---------------------+------+-----+---------+----------------+
| id             | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| created_at     | datetime            | YES  |     | NULL    |                |
| updated_at     | datetime            | YES  |     | NULL    |                |
| deleted_at     | datetime            | YES  | MUL | NULL    |                |
| basic_time     | datetime            | YES  |     | NULL    |                |
| basic_sentence | varchar(256)        | NO   | PRI | NULL    |                |
| nickname       | varchar(256)        | YES  |     | NULL    |                |
| email          | varchar(256)        | YES  |     | NULL    |                |
| age            | tinyint(3) unsigned | YES  |     | NULL    |                |
+----------------+---------------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)

顺带引入结构体标记(tags)的介绍

详细完整的介绍请点击这里

  1. gorm:"column:xxx":指定数据库表中对应字段的名称。例如,gorm:"column:user_name" 表示将结构体字段映射到数据库表中的 user_name 字段。
  2. gorm:"type:xxx":指定数据库字段的数据类型。例如,gorm:"type:int" 表示将结构体字段映射到数据库表中的 int 类型字段。
  3. gorm:"size:xxx":指定数据库字段的长度或大小。例如,gorm:"size:255" 表示将结构体字段映射到数据库表中的长度为 255 的字段。
  4. gorm:"not null":指定数据库字段不能为空。例如,gorm:"not null" 表示将结构体字段映射到数据库表中的非空字段。
  5. gorm:"default:xxx":指定数据库字段的默认值。例如,gorm:"default:'unknown'" 表示将结构体字段映射到数据库表中的默认值为 'unknown' 的字段。
  6. gorm:"unique":指定数据库字段的唯一性。例如,gorm:"unique" 表示将结构体字段映射到数据库表中的唯一字段。
  7. gorm:"index":指定数据库字段的索引。例如,gorm:"index" 表示将结构体字段映射到数据库表中的索引字段。
  8. gorm:"primary_key":指定数据库字段为主键。例如,gorm:"primary_key" 表示将结构体字段映射到数据库表中的主键字段。

GORM中的CURD

CURD通常指的是数据库的增删改查操作,本小节将系统地介绍如何使用GORM来实现CURD操作,注:本文中db变量全部默认为*gorm.DB类型

创建记录

首先定义相关Model

go 复制代码
type User struct{
    ID uint64 `gorm:"primaryKey"`
    Name String `gorm:"default:'七海'"`
    Age uint8
}

接着使用NewRecord(实例)方法来判断检查给定的模型实例是否是一个新记录。

go 复制代码
user1:=User{Name:"Nanami",Age: 19}

if db.NewRecord(user1){//若为新纪录则返回true
    db.Create(&user1)//创建user1实例的新纪录
}

查找记录

一般查询

go 复制代码
 //用于保存返回结果
var user1 User
var users []User
db.First(&user1)//获取表中的第一条记录
db.Take(&user1)//随机获取一条数据
db.Last(&user1)//查找主键排序的最后一条记录
db,Find(&usres)//查找所有记录

使用Where进行条件查找

go 复制代码
db.Where("name=?","Nanami").Fisrt(&user1)
//等价于SELECT * FROM t_users WHERE name='Nanami' LIMIT 1(下面的语句也类似)
db.Where("name<>?","七海").find(&users)
db.Where("name IN (?)",[]string{"七海","Nanami"}).Find(&users)
db.Where("name=? AND age>=?","Nanami",20).Find(&users)
db.Where("created_at BETWEEN ? AND ?",last_Sunday,today).Find(&users)

更新数据库

go 复制代码
db.First(&user1)
user1.Name="new_Nanami"
user1.age=100
db.save(&user1)

db.save()方法会默认更新该对象的所有字段,即使你没有赋值

如果你只是想更新指定字段,那么你可以尝试使用Update或者Updates方法

go 复制代码
db.Model(&user1).Update("name","Nakira")
//上述指令作用,修改user1的name字段值为"Nakira"
//需要注意的是name是在数据表中的列的名称,而不是结构体的名称,user1是数据库中的实例
db.Model(&uesr1).Where("active=?",true).Update("name","Nakira")
db.Model(&user2).Update(map[string]interface{}{"name":"Nanami","age":19,"active":false})
//使用map结构来实现更新多个属性

如果你想要忽略某些字段那么你可以考虑使用Select,Omit来实现

sql 复制代码
db.Model(&user1).Select("name").Update(map[string]interface{}{"name":"Nanami","age":19,"active":false})//选中只更新name字段
db.Model(&user1).Omit("name").Update(map[string]interface{}{"name":"Nanami","age":19,"active":false})//忽略更新name字段

删除记录

Warning: 删除记录时候请确保主键不为空,`GROM`通过主键删除记录,如果主键为空,那么会删除该Model下的所有记录

g0 复制代码
db.Delete(&user1)//删除现有记录
db.Where("name=?","Nanami").Delete(User{})//批量删除匹配的数据

本人初学gorm,难免有错误之处,请各位多多指正、多多包涵。2023.7.28

相关推荐
千慌百风定乾坤7 小时前
Go 语言入门指南:基础语法和常用特性解析(下) | 豆包MarsCode AI刷题
青训营笔记
FOFO7 小时前
青训营笔记 | HTML语义化的案例分析: 粗略地手绘分析juejin.cn首页 | 豆包MarsCode AI 刷题
青训营笔记
滑滑滑2 天前
后端实践-优化一个已有的 Go 程序提高其性能 | 豆包MarsCode AI刷题
青训营笔记
柠檬柠檬2 天前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记
用户967136399652 天前
计算最小步长丨豆包MarsCodeAI刷题
青训营笔记
用户52975799354723 天前
字节跳动青训营刷题笔记2| 豆包MarsCode AI刷题
青训营笔记
clearcold3 天前
浅谈对LangChain中Model I/O的见解 | 豆包MarsCode AI刷题
青训营笔记
夭要7夜宵4 天前
【字节青训营】 Go 进阶语言:并发概述、Goroutine、Channel、协程池 | 豆包MarsCode AI刷题
青训营笔记
用户336901104444 天前
数字分组求和题解 | 豆包MarsCode AI刷题
青训营笔记
dnxb1234 天前
GO语言工程实践课后作业:实现思路、代码以及路径记录 | 豆包MarsCode AI刷题
青训营笔记