Gorm操作MySQL

12/8/2021 Golang

# Go使用GORM操作MySQL

  • GORM概述

    The fantastic ORM library for Golang ,超棒的Go 语言ORM 类库

    通俗的来说就是一个写好的库,使用库定义好的类实例化出的对象来操作MySQL,让对数据库的操作变得更加容易

  • 导入包

      import (
        _ "github.com/go-sql-driver/mysql" //myslq驱动
        "github.com/jinzhu/gorm"  
        _ "github.com/jinzhu/gorm/dialects/mysql"
      )
    
    1
    2
    3
    4
    5
  • 快速开始

    package main
    
    import (
        _ "github.com/go-sql-driver/mysql" //myslq驱动
        "github.com/jinzhu/gorm"  
        _ "github.com/jinzhu/gorm/dialects/mysql"
      )
    
    // 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") //用户名:密码@(URL)/数据库名?charset=utf8mb4&parseTime=True&loc=Local
    	if err!= nil{
    		panic(err)
    	}
    	defer db.Close()
    
    	// 自动迁移
    	db.AutoMigrate(&UserInfo{})
    
    	u1 := UserInfo{1, "七米", "男", "篮球"}
    	u2 := UserInfo{2, "沙河娜扎", "女", "足球"}
    	// 创建记录
    	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)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
  • 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
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    模型定义示例

    type User struct {
      gorm.Model
      Name         string
      Age          sql.NullInt64
      Birthday     *time.Time
      Email        string  `gorm:"type:varchar(100);unique_index"`
      Role         string  `gorm:"size:255"` // 设置字段大小为255
      MemberNumber *string `gorm:"unique;not null"` // 设置会员号(member number)唯一并且不为空
      Num          int     `gorm:"AUTO_INCREMENT"` // 设置 num 为自增类型
      Address      string  `gorm:"index:addr"` // 给address字段创建名为addr的索引
      IgnoreMe     int     `gorm:"-"` // 忽略本字段
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    结构体标记(Tag) 描述
    Column 指定列名
    Type 指定列数据类型
    Size 指定列大小, 默认值255
    PRIMARY_KEY 将列指定为主键
    UNIQUE 将列指定为唯一
    DEFAULT 指定列默认值
    PRECISION 指定列精度
    NOT NULL 将列指定为非 NULL
    AUTO_INCREMENT 指定列是否为自增类型
    INDEX 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引
    UNIQUE_INDEX INDEX 类似,只不过创建的是唯一索引
    EMBEDDED 将结构设置为嵌入
    EMBEDDED_PREFIX 设置嵌入结构的前缀
    - 忽略此字段
  • 表名

    表名默认就是结构体名称的复数,例如:

    type User struct {} // 默认表名是 `users`
    
    // 将 User 的表名设置为 `profiles`
    func (User) TableName() string {
      return "profiles"
    }
    
    func (u User) TableName() string {
      if u.Role == "admin" {
        return "admin_users"
      } else {
        return "users"
      }
    }
    
    // 禁用默认表名的复数形式,如果置为 true,则 `User` 的默认表名是 `user`
    db.SingularTable(true)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    也可以通过Table()指定表名:

    // 使用User结构体创建名为`deleted_users`的表
    db.Table("deleted_users").CreateTable(&User{})
    
    var deleted_users []User
    db.Table("deleted_users").Find(&deleted_users)
    //// SELECT * FROM deleted_users;
    
    db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
    //// DELETE FROM deleted_users WHERE name = 'jinzhu';
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 列名

    列名由字段名称进行下划线分割来生成

    type User struct {
      ID        uint      // column name is `id`
      Name      string    // column name is `name`
      Birthday  time.Time // column name is `birthday`
      CreatedAt time.Time // column name is `created_at`
    }
    
    1
    2
    3
    4
    5
    6

    可以使用结构体tag指定列名:

    type Animal struct {
      AnimalId    int64     `gorm:"column:beast_id"`         // set column name to `beast_id`
      Birthday    time.Time `gorm:"column:day_of_the_beast"` // set column name to `day_of_the_beast`
      Age         int64     `gorm:"column:age_of_the_beast"` // set column name to `age_of_the_beast`
    }
    
    1
    2
    3
    4
    5
  • 查询大法

    • 查询单个对象

      // 获取第一条记录(主键升序)
      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.First(&user)
      result.RowsAffected // 返回找到的记录数
      result.Error        // returns error or nil
      
      // 检查 ErrRecordNotFound 错误
      errors.Is(result.Error, gorm.ErrRecordNotFound)
      
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19

      如果你想避免ErrRecordNotFound错误,你可以使用Find,比如db.Limit(1).Find(&user)Find方法可以接受struct和slice的数据。

    • 查询全部对象

      // 获取全部记录
      result := db.Find(&users)
      // SELECT * FROM users;
      
      result.RowsAffected // 返回找到的记录数,相当于 `len(users)`
      result.Error        // returns error
      
      1
      2
      3
      4
      5
      6
    • 条件查询

      // 获取第一条匹配的记录
      db.Where("name = ?", "jinzhu").First(&user)
      // SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
      
      // 获取全部匹配的记录
      db.Where("name = ?", "jinzhu").Find(&users)
      // SELECT * FROM users WHERE name = 'jinzhu';
      
      // IN
      db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
      // SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');
      
      // AND
      db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
      // SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
      
      // Time
      db.Where("updated_at > ?", lastWeek).Find(&users)
      // SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
      
      // Struct
      db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
      // SELECT * FROM users WHERE name = "jinzhu" AND age = 20 ORDER BY id LIMIT 1;
      
      // Map
      db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
      // SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
      
      // 主键切片条件
      db.Where([]int64{20, 21, 22}).Find(&users)
      // SELECT * FROM users WHERE id IN (20, 21, 22);
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31

      注意 当使用结构作为条件查询时,GORM 只会查询非零值字段。这意味着如果您的字段值为 0''false 或其他 零值 (opens new window),该字段不会被用于构建查询条件,例如:

      db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)// SELECT * FROM users WHERE name = "jinzhu";
      
      1

      当使用 struct 进行查询时,你可以通过向 Where() 传入 struct 来指定查询条件的字段、值、表名,例如:

      db.Where(&User{Name: "jinzhu"}, "name", "Age").Find(&users)
      // SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
      
      db.Where(&User{Name: "jinzhu"}, "Age").Find(&users)
      // SELECT * FROM users WHERE age = 0;
      
      1
      2
      3
      4
      5
  • 增加、删除、更新以及更多的查询大法

    gorm中文文档 (opens new window)😁

Last Updated: 10/28/2024, 3:08:38 PM