GORM实践 | 豆包MarsCode AI刷题

30 阅读3分钟
  • GORM

  1. 什么是ORM?

    Object Relational Mapping 对象关系映射

    对象:程序中的对象/实例,例如Go中的结构体实例

    关系:关系数据库,例如MySQL

    数据表<-->结构体
    数据行<-->结构体实例
    字段  <-->结构体字段
    
  2. ORM优缺点

    优点:

    • 提高开发效率

    缺点:

    • 牺牲执行性能
    • 牺牲灵活性
    • 弱化SQL能力

    附:

    数据库关闭

    defer db.Close()

    defer一般用于资源的释放和异常的捕捉, 作为Go语言的特性之一. defer 语句会将其后面跟随的语句进行延迟处理. 意思就是说 跟在defer后面的语言 将会在程序进行最后的return之后再执行. 在defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。

  3. Model定义

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

    • gorm.Model

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

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

      可以将它嵌入到你自己的模型中:

      // 将 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`字段注入到`User`模型中
      type User struct {
        gorm.Model
        Name string
      }
      

      当然你也可以完全自己定义模型:

      // 不使用gorm.Model,自行定义模型
      type User struct {
        ID   int
        Name string
      }
      
    • 结构体标记

      使用结构体声明模型时,标记(tags)是可选项。

  4. 主键、表名、列名的约定

    • 主键(Primary Key)

      GORM 默认会使用名为ID的字段作为表的主键。

      type User struct {
        ID   string // 名为`ID`的字段会默认作为表的主键
        Name string
      }
      ​
      // 使用`AnimalID`作为主键
      type Animal struct {
        AnimalID int64 `gorm:"primary_key"`
        Name     string
        Age      int64
      }
      
    • 表名(Table Name)

      表名默认就是结构体名称的复数,也可以通过Table()指定表名。

    • 列名(Column Name)

      列名由字段名称进行下划线分割来生成,可以使用结构体tag指定列名。

    • 时间戳跟踪

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

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

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

  5. CRUD(增删改查)

注意: 所有字段的零值, 比如0, "",false或者其它零值,都不会保存到数据库内,但会使用默认值。 如果想避免这种情况,可以考虑使用指针或实现 Scanner/Valuer接口。

当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果字段值为0''false或者其他零值时,将不会被用于构建查询条件,同样可以使用指针或实现 Scanner/Valuer 接口来避免这个问题。