xorm多表连接查询

SQL的连接查询可以将多个表的数据查询出来,形成一个中间表。在sql中为JOIN关键字。最常用的是LEFT JOIN,RIGHT JOIN,INNER JOIN,OUTER JOIN

xorm框架是基于go语言的orm框架同样支持连接查询,由于xom及支持原生的sql查询也支持基于xorm的方法查询,本文章将基于两种不同的方式做比较。

select order_item.id,order_item.order_id,order_item.product_name,order_item.product_id,order_item.product_area_id,order_item.card_type,order_item.card_num,order_item.container_name
,order_item.container_id,order_item.using_cpu,order_item.using_ram,order_item.video_memory,order_item.free_data_disk,order_item.expand_data_disk,order_item.max_cuda_version,order_item.container_name
,order_item.charge_mode,order_item.rent_start_time,order_item.rent_end_time,order_item.deleted_at,order_item.created_at,order_item.updated_at
,order_main.id as oid,order_main.customer_id as ocustomer_id ,order_main.order_amount as order_amount
from order_item LEFT JOIN order_main on order_item.order_id = order_main.id where order_main.customer_id = '1970' and order_main.order_id = '1'

如上面所示为一个LEFT JOIN的左连接查询,可以看到使用sql语句,需要将所有的字段通过表名.字段名列举出来,当然如果保证所有的字段都不同名,直接*也可以。

可以看到这样写的sql是比较麻烦的,如果放在go中就更显得臃肿了。

err = MasterDB.SQL("select * from (select financial_flow.id as fid ,financial_flow.number as number,financial_flow.customer_id as customer_id,financial_flow.customer_name as customer_name,financial_flow.type,financial_flow.recharge_way as recharge_way,financial_flow.money,financial_flow.operator_id as operator_id, order_item.id,order_item.order_id,order_item.product_name,order_item.product_id,order_item.product_area_id,order_item.card_type,order_item.card_num,order_item.container_name ,order_item.container_id,order_item.container_state,order_item.using_cpu,order_item.using_ram,order_item.video_memory,order_item.free_data_disk,order_item.expand_data_disk,order_item.max_cuda_version from  order_item LEFT JOIN financial_flow on financial_flow.number = order_item.order_id ) as a RIGHT JOIN order_main on a.order_id = order_main.id limit ?,?", paginator.curPage, paginator.perPage).Find(&result)

代码就会变成这样,阅读性和维护性很差:

在这里插入图片描述

由于数据库的局限性,所有数据只能通过二维表的格式来展现,因此也没有分层结构,没有层次也不便于阅读。但是在程序中的数据结构是多种多样的,有层次的,例如Go的结构体就可以很好的与数据库的数据对接。

xorm中使用结构体来表述连接关系,一个结构体为一个表,连接多少个表就有多少个同级的结构体。

官网案例:

//结构体1
type Group struct {
    Id int64
    Name string
}

//结构体2
type User struct {
    Id int64
    Name string
    GroupId int64 `xorm:"index"`
}

数据库表为user表,group表分别包含结构体字段。如果连接查询sql为:

select group.id as gid,group.name as gname,user.id as uid , user.name as uname,user.group_id as group_id from group LEFT JOIN user on group.id = user.group_id

由于两个表同名了很多字段,因此还需要使用as重命名,这样在查询的过程中有需要一个新的结构体赋值。显然这样是很不方便的。

xorm基于结构体特性设计了新的赋值方式,将结构体嵌套,即使重名称分属于不同结构体也不冲突。

type UserGroup struct {
    User `xorm:"extends"`
    Group `xorm:"extends"`
}

使用嵌套表示连接查询的结果,必须使用xorm的tag并有extends关键字。

xorm提供了Join方法实现连接,其有三个参数engine.Table("user").Join("INNER", "group", "group.id = user.group_id")

第一个参数为连接类型,第二个参数为连接表,第三个参数为on的条件。而且Join的返回值还是engine仍是过程量,可通过Get或者Find方法查询结果。

users := make([]UserGroupType, 0)
engine.Table("user").Join("INNER", "group", "group.id = user.group_id").
    Join("INNER", "type", "type.id = user.type_id").
    Find(&users)

同时,在使用Join时,也可同时使用Where和Find的第二个参数作为条件,Find的第二个参数同时也允许为各种bean来作为条件。Where里可以是各个表的条件,Find的第二个参数只是被关联表的条件。

案例:

type Order2GpuServer struct {
	OrderMain     `xorm:"extends"`
	OrderItem `xorm:"extends"`
	Product      `xorm:"extends"`
	Node         `xorm:"extends"`
}
//订单对象
var order2GpuServers []models.Order2GpuServer
session := MasterDB.Join("LEFT", "order_item", "order_main.id = order_item.order_id")
session = session.Join("LEFT", "product", "order_item.product_id = product.id")
session = session.Join("LEFT", "node", "product.node_id = node.id")
session.Find(&order2GpuServers)

debug的时候可以看到,连接查询的灭个表都赋值到对应的结构体中了:

在这里插入图片描述

在这里插入图片描述

xorm通过结构体将sql查询的结果转化为层次分明的结构体数据,使数据更有层次感,热不是二维表全部展示,在程序中也方便赋值。

虽然xorm框架在程序中以结构体的i形式保存了数据的中间量,但是在持久化时,脱离程序,数据就会又变为二维形式即全部显示在一起,这样如果有同名的话,就有冲突,xorm的策略时不显示同名的字段。

如下直接序列化返回json字符时没有显示同名的,应为同名的都不显示:

在这里插入图片描述

如果需要显示就需要再创建一个新的结构体,通过连接返回的结构体依次赋值:

在这里插入图片描述
这样通过结构体.字段名来来获取不同个字段的值。

Join("","","")改变查询的方式为第一个参数LEFT,RIGHT,INNER,OUTER.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xvwen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值