Gorm 预加载及输出处理(一)- 预加载应用
单条关联查询
先创建两个关联模型:
// 用户模型
type User struct {
    gorm.Model
    Username string    `gorm:"type:varchar(20);not null;unique"`
    Email    string    `gorm:"type:varchar(64);not null;unique"`
    Role     string    `gorm:"type:varchar(32);not null"`
    Active   uint8     `gorm:"type:tinyint unsigned;default:1"`
    Profile  Profile   `gorm:"foreignkey:UserID;association_autoupdate:false"`
}
// 用户信息模型
type Profile struct {
    gorm.Model
    UserID   uint      `gorm:"type:int unsigned;not null;unique"`
    Username string    `gorm:"type:varchar(20);not null;unique"`
    Nickname string    `gorm:"type:varchar(64);not null;unique"`
    Phone    string    `gorm:"type:varchar(32)"`
    Gender   uint8     `gorm:"type:tinyint unsigned;default:0"`
    Birthday time.Time `gorm:"type:datetime;default:null"`
    Sign     string    `gorm:"type:varchar(255)"`
    Avatar   string    `gorm:"type:text"`
}
直接查询单条 User 记录
var user User
DB.Debug().First(&user)
这里省略 JSON 序列化输出的过程,直接看输出,类似这样:
{
    "ID": 1,
    "CreatedAt": "2020-03-11T18:26:13+08:00",
    "UpdatedAt": "2020-03-11T18:28:41+08:00",
    "DeletedAt": null,
    "Username": "test",
    "Email": "text@demo.dev",
    "Role": "member",
    "Active": 1,
    "Profile": {
        "ID": 0,
        "CreatedAt": "001-01-01T00:00:00Z",
        "UpdatedAt": "001-01-01T00:00:00Z",
        "DeletedAt": null,
        "UserID": 0,
        "Username": "",
        "Nickname": "",
        "Phone": "",
        "Gender": 0,
        "Birthday": "0001-01-01T00:00:00Z",
        "Sign": "",
        "Avatar": ""
    }
}
可以看到,虽然有输出 Profile 字段,但是里面的字段值全为零值,也就是说直接查询 User 并不会默认把关联的 Profile 一同查询出来。
可能有童鞋要问了,没查询 Profile 为什么还会输出空值的 Profile 字段呢?这是因为 JSON 序列化是按照模型的定义自动处理,User 模型中定义了 Profile 字段,如进行关联查询且能查到结果,那么就赋值给 Profile 字段,否则 Profile 依然序列化输出,只不过 Profile 里面的字段全都为空值。
接下来看下如何使用关联查询获取完整的 User 数据:
// 方式一:手动查询关联数据
var user User
// 第一步,查询用户
DB.Debug().First(&user)
// 第二步,查询关联的用户信息
// 注意,Related 方法第二个参数为 Profile 的外键
DB.Debug().Model(&user).Related(&user.Profile, "UserID")
// 方式二:也可以使用预加载方式查询关联数据
DB.Debug().Model(&user).Preload("Profile").First(&user)
可以看到,使用预加载方式语法更简练,实际上底层还是2个查询,只不过 gorm 帮我们封装好了,现在可以获取到完整的数据,类似这样:
{
    "ID": 1,
    "CreatedAt": "2020-03-11T18:26:13+08:00",
    "UpdatedAt": "2020-03-11T18:28:41+08:00",
    "DeletedAt": null,
    "Username": "test",
    "Email": "text@demo.dev",
    "Role": "member",
    "Active": 1,
    "Profile": {
        "ID": 1,
        "CreatedAt": "2020-03-11T18:26:13+08:00",
        "UpdatedAt": "2020-03-11T18:26:13+08:00",
        "DeletedAt": null,
        "UserID": 1,
        "Username": "test",
        "Nickname": "test",
        "Phone": "",
        "Gender": 0,
        "Birthday": "0001-01-01T00:00:00Z",
        "Sign": "",
        "Avatar": ""
    }
}
列表关联查询
列表的关联查询和单条关联查询类似,不过手动进行列表的关联查询很繁琐,得先查出 User 列表,然后再查询一次 Profile 列表获取对应的数据,最后整合两部分数据。直接使用预加载就很简单了,代码如下:
var users []User
// 使用预加载查询
DB.Debug().Model(&User{}).Preload("Profile").Find(&users)
输出如下:
[
    {
        "ID": 1,
        "CreatedAt": "2020-03-11T18:26:13+08:00",
        "UpdatedAt": "2020-03-11T18:28:41+08:00",
        "DeletedAt": null,
        "Username": "test",
        "Email": "text@demo.dev",
        "Role": "member",
        "Active": 1,
        "Profile": {
            "ID": 1,
            "CreatedAt": "2020-03-11T18:26:13+08:00",
            "UpdatedAt": "2020-03-11T18:26:13+08:00",
            "DeletedAt": null,
            "UserID": 1,
            "Username": "test",
            "Nickname": "test",
            "Phone": "",
            "Gender": 0,
            "Birthday": "0001-01-01T00:00:00Z",
            "Sign": "",
            "Avatar": ""
        }
    },
    ...
]
gorm 底层使用这两条查询:
SELECT * FROM `user`  WHERE `user`.`deleted_at` IS NULL
SELECT * FROM `profile`  WHERE `profile`.`deleted_at` IS
 NULL AND ((`user_id` IN (1,2,3,4,5,6)))
gorm 还在内部把两条查询的数据都整合好了,使用相当方便。
这只是一个简单的预加载应用,更多应用可参考 Gorm官方文档-预加载。
小结
预加载在单条关联查询中提供了更简洁的语法,在列表关联查询中不仅解决了关联查询 N + 1 的问题,还自动整合了数据,方便快捷。
到这里,一个简单的预加载查询就完成了,但是可以发现查询输出还有很多瑕疵,如:只查询 User 也会带上空值 Profile,字段名和模型定义的一样都是首字母大写,并且时间格式不友好。
这就衍生出了几个问题:
- 如何自定义输出结构,只输出指定字段?
- 如何自定义字段名,并去掉空值字段?
- 如何自定义时间格式?
下一篇将介绍如何处理查询输出,解决上述问题。
如发现任何问题,欢迎指正,谢谢观看!
参考资料: Gorm官方文档
本文出处:https://www.cnblogs.com/zhenfengxun/
本文链接:https://www.cnblogs.com/zhenfengxun/p/12486325.html
Gorm 预加载及输出处理(一)- 预加载应用的更多相关文章
- Gorm 预加载及输出处理(二)- 查询输出处理
		上一篇<Gorm 预加载及输出处理(一)- 预加载应用>中留下的三个问题: 如何自定义输出结构,只输出指定字段? 如何自定义字段名,并去掉空值字段? 如何自定义时间格式? 这一篇先解决前两 ... 
- Gorm 预加载及输出处理(三)- 自定义时间格式
		前言 Gorm 中 time.Time 类型的字段在 JSON 序列化后呈现的格式为 "2020-03-11T18:26:13+08:00",在 Go 标准库文档 - time 的 ... 
- 图片预加载和AJAX的图片预加载
		利用js实现图片预加载,加载所需要图片的路径与名称即可,很容易实现,该方法尤其适用预加载大量的图片: <div class="hidden"> <script t ... 
- HTML5的页面资源预加载技术(Link prefetch)加速页面加载
		不管是浏览器的开发者还是普通web应用的开发者,他们都在做一个共同的努力:让Web浏览有更快的速度感觉.有很多已知的技术都可以让你的网站速度变得更快:使用CSS sprites,使用图片优化工具,使用 ... 
- 转载:用Jquery实现的图片预加载技术,可以实现有序加载和无序加载!
		一.背景 我们在做页面的时候,从用户体验的角度出发,肯定是希望用户以最快的速度看到完整的页面信息,但在实际情况中经常会遇到些问题. 比如受网速影响,页面加载素材的时间比较长,页面会出现短时间的错乱或者 ... 
- js原生图片懒加载 或 js原生图片预加载,html标签自定义属性
		使用原声js来实现图片预加载,或图片懒加载,小伙伴们可以根据项目需要来结合vue或者是react来进行修改. 一.什么是图片懒加载或什么是图片预加载 当访问一个页面的时候,先把img元素或是其他元素的 ... 
- moviepy音视频剪辑:使用VideoFileClip、AudioFileClip和write_videofile、write_audiofile进行音视频的加载和输出
		专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 在本地进行音视频处理时,首先要从视频文件 ... 
- moviepy音视频剪辑:音视频的加载和输出
		专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 在本地进行音视频处理时,首先要从视频文件 ... 
- js图片加载效果(延迟加载+瀑布流加载)
		概述 两种图片加载的效果:一种是遇到图片较多时,带读条效果的加载提示:另一种是根据滑块的位置进行预加载,用户不察觉的情况下,实现瀑布流的加载效果 详细 代码下载:http://www.demodash ... 
- Hi3559AV100 NNIE开发(7) Ruyistudio 输出mobileface_func.wk与板载运行mobileface_chip.wk输出中间层数据对比
		前面随笔讲了关于NNIE的整个开发流程,并给出了Hi3559AV100 NNIE开发(5)mobilefacenet.wk仿真成功量化及与CNN_convert_bin_and_print_featu ... 
随机推荐
- 吴裕雄--天生自然python学习笔记:python处理word文档
			Office 文件是我们日常工作生活中都经常用到的文件格 式,其中以 Word 格式的文件最为常用 . Python 可通过 Win32com 纽件对 Micro so位 Office 文件 进行存取 ... 
- Android内存调优的一些方法
			一.巧妙使用软引用和弱引用 软引用,系统内存紧张时会回收软引用对象,一般用用高速缓存,例如图片缓存,我们一般通过内存缓存图片来提高图片加载速度,但内存吃紧的时候可以通过软引用及时对图片资源回收. 弱引 ... 
- OSI体系结构(七层)
			OSI体系结构,意为开放式系统互联.国际标准组织(国际标准化组织)制定了OSI模型.这个模型把网络通信的工作分为7层,分别是物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 1至4层被认为 ... 
- ospf实验二
			R1,R2,R3为17.1.1.0网段 1. R4先做rip #rip 1 #version 2 #undo sum.. #netwokr 14.0.0.0 实验第四条 标记tag 100 在R4上做 ... 
- 吴裕雄--天生自然Android开发学习:android 背景相关与系统架构分析
			1.Android背景与当前的状况 Android系统是由Andy Rubin创建的,后来被Google收购了:最早的版本是:Android 1.1版本 而现在最新的版本是今年5.28,Google ... 
- Netflix拒上戛纳电影节,能给国内视频产业什么启示?
			当新事物诞生时,总是会遭到质疑,甚至是排斥!因为新事物的活力.潜力,都对保守的传统事物产生了极大的冲击.就像有声电影刚刚诞生时,一代"默片大师"卓别林就对其进行了激烈的反对.他认为 ... 
- MAYA安装未完成,某些产品无法安装的解决方法
			MAYA提示安装未完成,某些产品无法安装该怎样解决呢?,一些朋友在win7或者win10系统下安装MAYA失败提示MAYA安装未完成,某些产品无法安装,也有时候想重新安装MAYA的时候会出现本电脑wi ... 
- RSA算法原理(简单易懂)
			1. 什么是RSA RSA算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法.在了解RSA算法之前,先熟悉下几个术语 根据密钥的使用方法,可以将密码分为对称密码和公钥密码 对称密码:加 ... 
- iOS应用程序开发——解决iOS7之前版本与之后版本下app启动图片跳动问题
			之前开发的app都是针对iOS6(兼容iOS5),所以在开发之初也出现了启动图片向下跳动的现象,通过网上的解决方法,代码中做了处理(“-20”): _imageView.frame = CGRectM ... 
- 吴裕雄--天生自然HTML学习笔记:HTML - XHTML
			XHTML 是以 XML 格式编写的 HTML. 什么是 XHTML? XHTML 指的是可扩展超文本标记语言 XHTML 与 HTML 4.01 几乎是相同的 XHTML 是更严格更纯净的 HTML ... 
