[TOC]
说明
请先阅读官方文档,由于官方文档对每个例子和概念解释比较简单,官方文档中个人认为比较难理解的概念在正文章节进行解释
本文须与官方文档伴食,否则将不知所云。
可对应 学习项目 实践验证。
参考
- V1官方文档
- ORM模型理念理解
正文
查询
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
-
调用
Where
方法进行条件查询带占位符的SQL语句+与占位符对应个数的参数;
用Struct或Map携带条件(条件关系为And)或用切片携带主键(多个主键关系为Or)
调用语义查询方法
结构体查询注意零值问题
条件查询Not
与Where类似,语义相反,条件格式也类似Where
条件查询Or
- 调用Where条件方法
- 调用Or条件方法,且条件字段与Where相同
- 调用语义查询方法
个人认为完全可以使用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辅助方法。
- 调用Where条件方法
- 选择性配合Attrs或Assign方法
- Attrs
- 数据库有符合Where指定条件记录则不起作用
- 反之则使用其指定的字段值构造结果
- Assign(数据库有无符合Where指定条件记录都用其指定字段值做替换)
- Attrs
- 调用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()方法