GORM-V1-CRUD

说明

请先阅读官方文档,由于官方文档对每个例子和概念解释比较简单,官方文档中个人认为比较难理解的概念在正文章节进行解释

本文须与官方文档伴食,否则将不知所云。

可对应 学习项目 实践验证。

参考

正文

查询

gorm.DB的方法定义采用了构造模式(所以才能连调多个方法),一个把较多方法用上的查询语句如下:

//伪代码,仅作方法简单罗列参考,且其中某些函数没有场景可以同时使用,顺序也没有严格思考。
db.Table(xxx).Select(xxx).Where(xxx).Or(xxx)Order(xxx).Limit(xxx).Offset(xxx).Attrs(xxx).FirstOrInit(&user).Count(xxx)

查询一条或多条

以下方法根据方法名语义查询(PS:个人称其为语义查询),涉及排序都是以主键排序

First/Take/Last/Find/

条件查询where

  1. 调用Where方法进行条件查询

    • 带占位符的SQL语句+与占位符对应个数的参数;

    • 用Struct或Map携带条件(条件关系为And)或用切片携带主键(多个主键关系为Or)

  2. 调用语义查询方法

结构体查询注意零值问题

条件查询Not

与Where类似,语义相反,条件格式也类似Where

条件查询Or

  1. 调用Where条件方法
  2. 调用Or条件方法,且条件字段与Where相同
  3. 调用语义查询方法

个人认为完全可以使用Where的In条件代替,如下:

// IN
db.Where("name IN (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
//// SELECT * FROM users WHERE name in ('jinzhu','jinzhu 2');

Inline Condition 内联条件

实际就是在语义查询方法内直接放查询条件(省略Where语句),条件格式包括:

  • 带占位符SQL及其条件值
  • Struct
  • Map

Extra Querying option 其它查询选项

通过gorm:query_option Tag格式指定查询行为

FirstOrInit与FirstOrCreate + 辅助方法Attrs与Assign

逻辑稍微复杂的语义查询方法,可选择性配合(可以不用)Attrs或Assign辅助方法。

  1. 调用Where条件方法
  2. 选择性配合Attrs或Assign方法
    • Attrs
      • 数据库有符合Where指定条件记录则不起作用
      • 反之则使用其指定的字段值构造结果
    • Assign(数据库有无符合Where指定条件记录都用其指定字段值做替换)
  3. 调用FirstOrInit或FirstOrCreate
    • FirstOrInit(数据库有无符合Where条件的记录都只根据步骤2规则构造结果)
    • FirstOrCreate(数据库有无符合Where条件的记录都根据步骤2规则构造结果并insert或update改变到数据库)

Advanced Query 高级查询

虽然叫高级查询,也确实逻辑较复杂,但是部分方法完全属于高级DML的方法式使用。与前文的简单DML方法式使用涉及较多参数格式和gorm抽象出来的易用方法不同,只要理解对用的高级DML就能理解这些方法的使用。所以对这部分方法不做过多解释。

  • 子查询
  • 选择字段:Select(xxx),不用的时候默认Select(*)
  • Order(xxx)
  • Limit(xxx)
  • Offset(int)
  • Count(xxx)
  • Group & Having
  • Joins(xxx)
Model
// Model specify the model you would like to run db operations
//    // update all users's name to `hello`
//    db.Model(&User{}).Update("name", "hello")
//    // if user's primary key is non-blank, will use it as condition, then will only update the user's name to `hello`
//    db.Model(&user).Update("name", "hello")
func (s *DB) Model(value interface{}) *DB {
	c := s.clone()
	c.Value = value
	return c
}

个人理解:作用与db.Table(xxx)相同,Table是通过数据库表名来指定要查询的表,Model是通过要查询的Struct的变量指针来指定要查询的表。

Pluck

对查询结果某字段取切片,相当于更简洁2、更省内存的 Select(一个字段);因为Select方式结果是对应的自定义Type切片,而Pluck方式结果是对应字段的Buildin Type切片,但二者有效内容一样。

Scan

对应面向对象思想,Find系列方法相当于直接查出PO,Scan相当于查出另外定义的VO;Scan查询的是PO的部分字段。

更新

gorm.DB的方法定义采用了构造模式(所以才能连调多个方法),一个把较多方法用上的更新语句如下:

db.Save(&user)
db.Model(&user).[Select(xxx)|Omit(xxx)].Where(xxx).Updates(xxx)
  • Save(&user) 更新id为&user.ID的记录的所有字段。
  • Update(xxx) 配合Model或Table更新指定表的指定字段,xxx可以是键值对/Map/Struct变量
    • Select(xxx) 配合此方法可以只更新指定字段
    • Omit(xxx) 配合此字段可以排除指定字段更新
  • 无Hooks更新(不会自动调用Model的Hooks方法,如:BeforeUpdate、AfterUpdate等)
    • UpdateColumn(xxx)
    • 批量更新
  • gorm.Expr(xxx) 在此方法中指定表达式
  • Set(xxx) 通过此方法指定gorm选项

删除

  • 主键删除—— db.Delete(&email),如果没指定主键删除该Model所有记录
  • 批量删除——配合Where或直接在Delete内指定筛选条件
  • 软删除—— model 有 DeletedAt 字段
  • 物理删除——配合Unscoped()方法
生老病死过于平淡,唯有求知聊以慰藉。
原文地址:https://www.cnblogs.com/wangbs95/p/13859641.html