Gorm框架

Gorm框架中文指南

简介


  1. ORM(Object Relational Mapping) 对象关系映射模式
    为了解决面向对象与关系型数据库存在的互不匹配现象的技 术.
    简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中.
  2. Gorm是面向golang语言的一种ORM框架,支持多种数据库的接入,如:MYSQL,PostgreSQL, SQLite, SQL server, Click house. 此框架弱化了开发者对于sql语言的掌握,使用提供的api进行底层数据库的访问.

1.连接数据库


  1. 简单连接
    import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    )
    //
    func main() {
    //mysql数据库的地址: "用户名:密码@tcp(127.0.0.1:3306)/数据库名?charset=urf8mb4parseTime=True&loc=Local"
    mysql_Addr := "user:pass@tcp(ip:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    //连接与错误处理
    db, err := gorm.Open(mysql.Open(mysql_Addr), &gorm.Config{})
    if err != nil {
    panic("failed to connect databaese!")
    }
    }
  2. 高级配置
      db, err := gorm.Open(mysql.New(mysql.Config{
    DSN: mysql_Addr,
    // DSN data source name
    DefaultStringSize: 256,
    // string 类型字段的默认长度
    DisableDatetimePrecision: true,
    // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
    DontSupportRenameIndex: true,
    // 重命名索引时采用删除并新建的方式,
    //MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
    DontSupportRenameColumn: true,
    // 用 `change` 重命名列,
    //MySQL 8 之前的数据库和 MariaDB 不支持重命名列
    SkipInitializeWithVersion: false,
    // 根据当前 MySQL 版本自动配置
    DriverName: "my_mysql_driver",
    //数据库驱动
    }), &gorm.Config{
    SkipDefaultTransaction: false,
    NamingStrategy: schema.NamingStrategy{
    //表名前缀
    TablePrefix: "gva_",
    //使用单数表名
    SingularTable: false,
    },
    //逻辑外链 (代码里面自带外键 外键关系)
    DisableForeignKeyConstraintWhenMigrating: true,
    })
  3. 连接池
    数据库操作都是通过连接去执行的,频繁的创建与销毁连接,比较浪费资源,因此会采用连接池对连接进行复用.GORM使用 database/sql维护理解成
    sqlDB, err := db.DB()

    // SetMaxIdleConns 设置空闲连接池中连接的最大数量
    sqlDB.SetMaxIdleConns(10)

    // SetMaxOpenConns 设置打开数据库连接的最大数量。
    sqlDB.SetMaxOpenConns(100)

    // SetConnMaxLifetime 设置了连接可复用的最大时间。
    sqlDB.SetConnMaxLifetime(time.Hour)

2. 模型

约定
默认情况下,gorm使用ID作为主键,使用结构体的小写复数英文为表名,字段名的小写为列名

结构体字段名首字母应该大写

关键标签
gorm:"primarykey" :主键
gorm:"column:db_list_name" :指定 db 列名
gorm:"not null" :指定列为 NOT NULL
gorm:"default:默认值" :定义列的默认值
gorm:"comment:注释" :迁移时为字段添加注释

表的创建
以结构体绑定表

*gorm.DB.AutoMigrate(&struct_Name{})

SQL操作(CRUD)

新增记录

Create函数

*gorm.DB.Create(&struct_Name{"key":"value"})
//2.只创建指定字段
*gorm.DB.Select("字段名").Create(&struct_Name{"key":"value"})
//3.创建除指定字段外的所有字段
*gorm.DB.Omit("字段名").Create(&struct_Name{"key":"value"})
//4.批量创建
*gorm.DB.Create(&[]struct_Name{ {}, {}, {} })
//输出错误和影响条数
fmt.Println("db err:", *gorm.DB.Error, " RowsAff:", *gorm.DB.RowsAffected)

查询记录

普通查询

  • 查询需要接受返回值,接受形式有map与struct
  1. 查询主键排序后的第一条 First 函数
  2. 查询一条记录,不指定字段排序 Take 函数
  3. 查询最后一条记录 Last 函数

检索

  1. 在函数内增加条件

  2. Where函数

    *gorm.DB.Where("字段名1 = ? AND 字段名2 = ?", "value").First(&接收)
  3. 多条件时可以使用的函数

  • AND 关键字
  • LIKE 关键字,配合使用通配符%,..
  • Or 函数
  • Not 函数
  1. 内联条件

    //将写入where的条件写在查询函数内
    *gorm.DB.First(&User4, "name = ?", "xxxx")
  2. 查询多条记录 Find函数

  3. 查询特定字段

  • select 函数

高级查询

  1. 智能选择字段
  • 使用新结构体进行接收数据

修改记录,更新记录

  1. Update函数 :只更新选择的字段
  2. Updates函数 :更新所有字段,,此时的两种形式,map与结构体,结构体零值则不参与更新
  3. Sava函数 :无论如何都更新,包括零值

删除记录

Delete函数
gorm中的Delete函数是进行了软删除,删除后,会有删除记录在表内

**UnScoped()**前缀硬删除

原生SQL

4.关联

默认外键名是拥有者的类型名加上其主键字段名

一对一 (one2one)

Belong to (属于)

例:你有一个目标

belong to :一个模型User与另一个模型Company建立连接.这种模型User的每一个实例都属于另一种模型Company的一个实例

// `User` 属于 `Company`,`CompanyID` 是外键
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}

type Company struct {
ID int
Name string
}
  • 结构一定要正确,不然会创建失败
  • (外键与结构体嵌入,外键为结构体名加ID, 结构体字段名与结构体名相同)
  1. 外键重写

  2. 能建立关联的关系创建与删除关系

    //创建关系
    *gorm.DB.Model(&User{}).Association("Company").Append(&Company_object)
    //删除关系
    *gorm.DB.Model(&User{}).Association("Company").Delete(&Company_object)

Has one (具有一个)

例:你有一个东西

// User 有一张 CreditCard,UserID 是外键
type User struct {
gorm.Model
CreditCard CreditCard
}

type CreditCard struct {
gorm.Model
Number string
UserID uint
}
  1. .Preload(""),预加载函数,提前拿出结构体数据

  2. 外键重写

  3. 能建立关联的关系创建与删除关系

    //创建关系
    *gorm.DB.Model(&User{}).Association("CreditCard").Append(&CreditCard_object)
    //删除关系
    *gorm.DB.Model(&User{}).Association("CreditCard").Delete(&CreditCard_object)

一对多

Has Many (有很多个)

例:有很多卡,并且这些卡只属于你

// User 有多张 CreditCard,UserID 是外键
type User struct {
gorm.Model
CreditCards []CreditCard
}

type CreditCard struct {
gorm.Model
Number string
UserID uint
}

Many to Many (多对多关系)

例:你会几门语言,但语言不不只属于你

// User 拥有并属于多种 language,`user_languages` 是连接表
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
gorm.Model
Name string
}

没有标签创建不了表 gorm:"many2many:user_languages;"
user_languages 是连接表

  • 为防止重复创建,应自己添加主键信息

关联模式 (One2One内有例子)

  1. 开始关联模式

    var user User
    db.Model(&user).Association("Languages")
    db.Model(&user).Association("Languages").Error
    • user 是关系主体模型,它的主键不能为空
    • 关系的字段名是 Languages
    • 如果匹配了上面两个要求,会开始关联模式,否则会返回错误
  2. 查找关联: 查找所有匹配的关联记录

    db.Model(&user).Association("Languages").Find(&languages)

    //查找带条件的关联
    codes := []string{"zh-CN", "en-US", "ja-JP"}
    db.Model(&user).Where("code IN ?", codes).Association("Languages").Find(&languages)

    db.Model(&user).Where("code IN ?", codes).Order("code desc").Association("Languages").Find(&languages)
  3. 添加关联
    为 many to many、has many 添加新的关联;为 has one, belongs to 替换当前的关联

    db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN})

    db.Model(&user).Association("Languages").Append(&Language{Name: "DE"})

    db.Model(&user).Association("CreditCard").Append(&CreditCard{Number: "411111111111"})
  4. 替换关联
    用一个新的关联替换当前的关联

    db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN})

    db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN)
  5. 删除关联
    如果存在,则删除源模型与参数之间的关系,只会删除引用,不会从数据库中删除这些对象。

    db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN})
    db.Model(&user).Association("Languages").Delete(languageZH, languageEN)
  6. 清空关联
    删除源模型与关联之间的所有引用,但不会删除这些关联

    db.Model(&user).Association("Languages").Clear()
  7. 关联计数: 返回当前关联的计数

    db.Model(&user).Association("Languages").Count()

    // 条件计数
    codes := []string{"zh-CN", "en-US", "ja-JP"}
    db.Model(&user).Where("code IN ?", codes).Association("Languages").Count()
  8. 批量处理数据
    关联模式也支持批量处理,例如:

    // 查询所有用户的所有角色
    db.Model(&users).Association("Role").Find(&roles)

    // 从所有 team 中删除 user A
    db.Model(&users).Association("Team").Delete(&userA)

    // 获取去重的用户所属 team 数量
    db.Model(&users).Association("Team").Count()

    // 对于批量数据的 `Append`、`Replace`,参数的长度必须与数据的长度相同,否则会返回 error
    var users = []User{user1, user2, user3}
    // 例如:现在有三个 user,Append userA 到 user1 的 team,Append userB 到 user2 的 team,Append userA、userB 和 userC 到 user3 的 team
    db.Model(&users).Association("Team").Append(&userA, &userB, &[]User{userA, userB, userC})
    // 重置 user1 team 为 userA,重置 user2 的 team 为 userB,重置 user3 的 team 为 userA、 userB 和 userC
    db.Model(&users).Association("Team").Replace(&userA, &userB, &[]User{userA, userB, userC})
    带 Select 的删除
    你可以在删除记录时通过 Select 来删除具有 has one、has many、many2many 关系的记录,例如:

    // 删除 user 时,也删除 user 的 account
    db.Select("Account").Delete(&user)

    // 删除 user 时,也删除 user 的 Orders、CreditCards 记录
    db.Select("Orders", "CreditCards").Delete(&user)

    // 删除 user 时,也删除用户所有 has one/many、many2many 记录
    db.Select(clause.Associations).Delete(&user)

    // 删除 users 时,也删除每一个 user 的 account
    db.Select("Account").Delete(&users)
  9. FullSaveAssociations
    想要更新关联的数据,您应该使用 FullSaveAssociations 模式:

    db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)

预加载(preload, joins)

//链式加载
*gorm.DB.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)
*gorm.DB.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{1,2,3,4,5})

注意 Join Preload 适用于一对一的关系,例如: has one, belongs to