您的位置:首页 > 编程语言 > Go语言

Gorm 预加载及输出处理(一)- 预加载应用

2020-03-13 14:38 232 查看
## 单条关联查询 先创建两个关联模型: ```go // 用户模型 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 记录 ```go var user User DB.Debug().First(&user) ``` 这里省略 JSON 序列化输出的过程,直接看输出,类似这样: ```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 数据: ```go // 方式一:手动查询关联数据 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 帮我们封装好了,现在可以获取到完整的数据,类似这样: ```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": 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 列表获取对应的数据,最后整合两部分数据。直接使用预加载就很简单了,代码如下: ```go var users []User // 使用预加载查询 DB.Debug().Model(&User{}).Preload("Profile").Find(&users) ``` 输出如下: ```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": 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 底层使用这两条查询: ```sql 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官方文档-预加载](http://gorm.io/zh_CN/docs/preload.html)。 ## 小结 预加载在单条关联查询中提供了更简洁的语法,在列表关联查询中不仅解决了关联查询 N + 1 的问题,还自动整合了数据,方便快捷。 到这里,一个简单的预加载查询就完成了,但是可以发现查询输出还有很多瑕疵,如:只查询 User 也会带上空值 Profile,字段名和模型定义的一样都是首字母大写,并且时间格式不友好。 这就衍生出了几个问题: - 如何自定义输出结构,只输出指定字段? - 如何自定义字段名,并去掉空值字段? - 如何自定义时间格式? 下一篇将介绍如何处理查询输出,解决上述问题。 如发现任何问题,欢迎指正,谢谢观看! ----- 参考资料: [Gorm官方文档](http://gorm.io/zh_CN/docs/)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐