gorm模块学习记录

  • Post author:
  • Post category:其他




gorm

用 go mod 管理模块

  • 导包

    import (
    	"time"
    
    	"gorm.io/driver/mysql"
    	gorm "gorm.io/gorm"
    )
    
  • 创建数据库引擎

    db, err := gorm.Open(mysql.Open(MYSQL_URL))
    if err != nil {
        fmt.Println(err)
    }
    
  • 定义模型结构体

    // column 字段名
    // type   字段类型  bool、int、uint、float、string、time、bytes
    // scale ,size  字段长度  size貌似不起作用
    // default   默认值
    // primaryKey 主键
    // index ,uniqueIndex   索引,唯一索引
    // unique   唯一约束
    // not null  非空约束
    // check     检查
    // autoIncrement  自增长   autoIncrementIncrement 自增长的步长
    // embedded    嵌套   embeddedPrefix  嵌套前缀
    // autoCreateTime   自动生成创建时间如果增操作没有传值
    // autoUpdateTime   自动生成更新时间如果更新操作没有传值
    // comment          备注信息
    type Class struct {
    	ID        uint64    `gorm:"Primarykey;autoIncrement"`
    	Name      string    `gorm:"column:my_name;Type:string;scale:100"`
    	CreatedAt time.Time // CreatedAt 会在创建时如果是空会自动创建当前时间
    	UpdatedAt time.Time `gorm:"autoCreateTime;autoUpdateTime"` // 更新也一样
    	Flag      bool      `gorm:"type:bool;default:1"` // bool在数据库是0或1
    }
    
    type Student struct {
    	gorm.Model    // 嵌套gorm定义的基类
    	Name string
    	Age  uint8
    	C_id uint64
    }
    
    // gorm提供了四种验证钩子函数
    func (s *Student) BeforeCreate(tx *gorm.DB) error {
    	if s.Age <= 18 {
    		return errors.New("Student.BeforeCreate")
    	}
    	return nil
    }
    
  • 设置自动迁移

    db.AutoMigrate(&Class{})
    db.AutoMigrate(&Student{})
    
  • // 相当于修改了结构体,数据库中会自动更新
    c1 := &Class{
        Name: "一年级一班",
    }
    db.Create(c1)
    db.Create(&Class{
        Name: "一年级二班",
    })
    
    // 指定字段新增  指定的字段是结构体重的字段,不是数据库的
    db.Select("Name").Create(&Class{Name: "三年二班"})
    // 忽略指定字段新增  忽略的字段就算是定义了也会忽略
    db.Omit("ID").Create(&Class{Name: "三年三班", ID: 100})
    // 批量插入
    users := make([]Student, 100)
    for i := 0; i < 100; i++ {
        users[i] = Student{Name: fmt.Sprintf("user_%d", i)}
    }
    // db.Create(users)
    // 分批新增     10个一批,插入后commit
    db.CreateInBatches(users, 10)
    
    // 钩子函数验证  
    rst1 := db.Create(&Student{Name: "18岁的天空", Age: 17})
    if rst1.Error != nil {         // 如果校验不通过,会报错
        fmt.Println(rst1.Error)    
    }
    
  • // 主键删除
    db.Delete(&Class{}, "1")
    // 条件删除
    db.Where("id = ?", 100).Delete(&Student{})
    // 删除指定的行
    var cc = make([]Class, 0)
    db.Find(&cc, "id > ?", 300)
    fmt.Println(len(cc))
    db.Delete(&cc)
    
  • // 修改符合条件的所有
    db.Model(&Class{}).Where("id = ?", "2").Update("my_name", "一年级三班")
    // 修改查询到的某条记录
    var ss Student
    db.Find(&ss, 1)
    ss.Name = "Lily"
    db.Save(&ss)
    // 条件更新  适用于多条记录时更新
    db.Model(&ss).Where("id = ?", "2").Update("name", "取什么名字好呢")
    // 多字段更新  利用结构体  或者  map
    db.Model(&ss).Updates(Student{Name: "sssssss", Age: 22})
    db.Model(&ss).Updates(map[string]interface{}{"name": "aaaaaaa", "age": 33})
    
    
  • // 单个
    var s Student
    db.First(&s) // 主键排序返回第一个
    fmt.Println(s)
    var s1 Student
    db.Last(&s1) // 主键倒序返回第一个
    fmt.Println(s1)
    var s3 Student
    db.Take(&s3) // 任意一个结果
    // 主键检索
    var s4 Student
    db.First(&s4, 1) // 主键 = 1
    fmt.Println(s4)
    var s5 Student
    db.First(&s5, "2") // 主键 = 2   字符串与整型一样的效果
    fmt.Println(s5)
    var s6 Student
    db.Find(&s6, []int{1, 2, 3}) // 主键 in (1,2,3)
    fmt.Println(s6)
    
    // 检索全部
    var c = make([]Class, 0)
    rst := db.Find(&c)
    fmt.Println(rst.RowsAffected)
    fmt.Println(c)
    fmt.Println(len(c))
    
    // 条件检索
    var c2 = make([]Class, 0)
    db.Where("my_name = ?", "一年级一班").Find(&c2) // 这里的条件是数据库中的字段条件
    fmt.Println(c2)
    
    // like
    var c3 = make([]Class, 0)
    db.Where("my_name like ?", "一年级%").Find(&c3)
    fmt.Println(c3)
    fmt.Println(len(c3))
    
    // between and
    var c4 = make([]Class, 0)
    db.Where("updated_at between ? and ?", time.Now().Add(-24*time.Hour), time.Now()).Find(&c4)
    fmt.Println(c4)
    fmt.Println(len(c4))
    
    // 结构体多条件
    var c5 = make([]Class, 0)
    db.Where(&Class{ID: 100}).Find(&c5)
    fmt.Println(c5)
    
    // map 多条件
    var c6 = make([]Class, 0)
    db.Where(map[string]string{"my_name": "三年二班"}).Find(&c6) // map 中的字段也是数据库中的字段
    fmt.Println(c6)
    
    // Find 字符串查询
    var c7 = make([]Class, 0)
    db.Find(&c7, "my_name", "三年二班")
    fmt.Println(c7)
    
    var c8 = make([]Class, 0)
    db.Find(&c8, &Class{Name: "一年级二班"})
    fmt.Println(c8)
    
    // 取反  Not 和 Where相似
    var c9 = make([]Class, 0)
    db.Not("my_name = ?", "三年二班").Find(&c9)
    fmt.Println(c9)
    
    // or
    var c10 = make([]Class, 0)
    db.Where("my_name = ?", "三年三班").Or("id < ?", 100).Order("id desc").Find(&c10) // order在最后没用 Find在最后才有用
    fmt.Println(c10)
    
    // 查询指定字段    除了指定字段,其余的都是零值
    var c11 = make([]Class, 0)
    db.Select("my_name", "id").Find(&c11, "id < ?", "10")
    fmt.Println(c11)
    
    // limit  offset
    var c12 = make([]Class, 0)
    db.Offset(5).Limit(10).Find(&c12)
    fmt.Println(c12)
    
  • 关联查询

    rst2 := make([]map[string]interface{}, 0)
    rows2, _ := db.Table("students").Select("name,age,classes.my_name").Joins("left join classes on students.c_id=classes.id").Where("students.c_id is not null").Rows()
    for rows2.Next() {
        var (
            name  string
            age   int
            class string
        )
        rows2.Scan(&name, &age, &class)
        rst2 = append(rst2, map[string]interface{}{"name": name, "age": age, "class": class})
    }
    fmt.Println(rst2)
    
  • 分组聚合

    type Result struct {
        Name string
        Cnt  int
    }
    var r = make([]Result, 0)
    // 查询条件要是数据库内的字段,返回值的结构体字段要大写
    db.Model(&Class{}).Select("my_name as name,count(id) as cnt").Group("name").Having("cnt > ?", 10).Find(&r)
    fmt.Println(r)
    
    // Rows 返回的是只有指定字段个数的通道
    // 有点像数据库中的游标 
    rows, _ := db.Table("classes").Select("my_name as name,count(id) as cnt").Group("name").Having("cnt > ?", 10).Rows()
    for rows.Next() {
        var (
            Name string
            Cnt  int
        )
        rows.Scan(&Name, &Cnt)
        fmt.Println(Name, Cnt)
    }
    
  • 原生SQL执行

    // 查询
    var rst Result
    db.Raw("select my_name,count(*) as cnt from classes group by name").Scan(&rst)
    
    // 增删改
    db.Exec("update classes set my_name = ? where id = ?","三年二班",1)
    
    

    代码托管在gitee https://gitee.com/mslsy/golang_study/tree/master/19_other_packages/19_4_gorm



版权声明:本文为weixin_41546513原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。