目录

  • 技术概述
  • 技术详述
  • 遇到的问题和解决过程
  • 总结
  • 参考文献

技术概述

Gorm框架可以进行多表联合查询,通过多表联合查询可以通过一条sql语句即可完成对数据库多表数据的获取,而不需要执行多条sql语句对数据库进行多次访问,从而加快了数据的处理速度。并且Gorm框架可以根据设计好的Model完成返回数据的封装,并不需要自己对数据进行再次封装。

技术详述

本次团队项目中我们获取评论数据时,不仅需要返回评论的相关信息,还要返回评论的作者的相关信息。如果不用Gorm的多表查询,则需要我们对每一条数据进行一次额外的查询和封装操作。下面是Gorm框架实现多表查询的具体步骤。

1. Model设计
评论和用户是一对多的关系,即一个评论属于一个用户,一个用户可以发布多条评论。

//评论
type Comment struct {
	ID          int64     `gorm:"column:ID;primaryKey"`
	UserID      string    `gorm:"column:userID"`
	Content     string    `gorm:"column:content"`
	CommentNum  int64     `gorm:"column:CommentNum"`
	TargetPost  int64     `gorm:"column:targetPost"`
	PublishTime time.Time `gorm:"column:publishTime"`
	State       int64     `gorm:"column:state"`
	Author      User      `gorm:"foreignKey:UserID"`
}

//用户
type User struct {
	ID            int64 `gorm:"column:ID;primaryKey"`
	Account       string
	Password      string
	PhoneNumber   string `gorm:"column:phoneNumber"`
	NickName      string `gorm:"column:nickName"`
	Major         string
	AvatarUrl     string `gorm:"column:avatarUrl"`
	Sex           string
	Area          string
	Year          int64
	TargetCollege string `gorm:"column:targetCollege"`
	TargetMajor   string `gorm:"column:targetMajor"`
	Slogan        string
	Balance       int64
	College       string
	State         int64     `gorm:"column:state"`
	RegisterTime  time.Time `gorm:"column:registerTime"`
}

可以看到在评论中我添加了User类型的Author字段,还在后面指定了外键是UserID,这样Gorm框架就可以根据UserID进行连表查询,并且不需要额外进行封装工作。

2. SQL语句设计

func SelectSingleCommentByCondition(db *gorm.DB, where map[string]interface{}) (Comment, int64, error) {
	var count int64 = 0
	var comment Comment
	err := db.Joins("Author").Where(where).First(&comment).Count(&count).Error
	if count == 0 {
		return comment, 0, errors.New("查询的记录不存在")
	}
	return comment, count, err
}

关键点在于要利用Joins()函数来选择连接查询的表,并且这里的函数参数要根据刚刚的Model设计中的命名来选择,比如在Comment中我们要查询的是Author字段,就传入“Author”。

3. 结果测试
测试函数:

package selectComment

import (
	fybDatabase "FybBackend/database"
	"FybBackend/routers/v1/backend/token"
	"FybBackend/routers/v1/exceptionHandler"
	"github.com/gin-gonic/gin"
	"github.com/hashicorp/go-multierror"
	"gorm.io/gorm"
)

func SelectCommentById(e *gin.Engine, db *gorm.DB) {
	e.GET("/v1/backend/comment/searchById", func(context *gin.Context) {
		if err := token.JwtVerify(context); err != nil {
			context.JSON(403, gin.H{
				"code":    403,
				"message": err.Error(),
			})
			return
		}

		var result *multierror.Error
		mp := make(map[string]interface{})
		mp["comment.id"] = context.DefaultQuery("id", "")
		post, _, err1 := fybDatabase.SelectSingleCommentByCondition(db, mp)
		result = multierror.Append(result, err1)

		code, msg := exceptionHandler.Handle(result)
		if code == 200 {
			context.JSON(code, gin.H{
				"code":    code,
				"message": "请求成功",
				"data":    post,
			})
		} else {
			context.JSON(code, gin.H{
				"code":    code,
				"message": msg,
			})
		}
	})
}

利用Postman对接口进行测试,返回结果如下:

java多条件查询mongo数据 gorm多条件查询_数据


可以看到测试函数中没有进行额外的数据封装,返回的结果结构就是按照Model设计中那样返回。

遇到的问题和解决过程

  • 问题:sql语句中如何确定是使用left join、right join 还是 inner join

通俗来说,对于表A和表B,left join返回包括表A中的所有记录和表B中联结字段相等的记录;right join返回包括表B中的所有记录和表A中联结字段相等的记录;inner join只返回两个表中联结字段相等的行。下面用一张图来直观的表示:

java多条件查询mongo数据 gorm多条件查询_数据_02


这里我们要查询的是评论的数据,因此选择left join。那么写的查询函数为什么用的是Joins()函数呢?通过查询Gorm框架的源代码我们可以发现,Joins函数就是使用了left join。


java多条件查询mongo数据 gorm多条件查询_字段_03

总结

  • 经过这次对Gorm框架的多表联合查询的学习,进一步加强了我对Gorm框架的掌握程度,对数据库的学习有了更深的理解。

参考文献

  • 参考博客
  • 参考文档