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
.
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/156133.html