Gorm一对多关系表操作与非固定结构表数据获取
目录
1.简介
2.环境及表说明
3.数据库连接
4.一对多表模型定义
5.不固定模型结构的表数据获取
6.小结
参考资料:
1. 简介
在一个实际工程中需要采集一些对象的属性信息,该工程涉及多个项目,每一个项目所采集的对象属性字段各不相同且无法提前预知,需要根据项目动态设计的字段生成对应项目的采集数据表。在服务端程序开发时,团队选择了Golang,其实自己也没有用过Go语言,也就正好借着这样的机会学习学习。实施过程中选择了Gorm来进行数据库操作,虽然这个库明面上是有一个较为完善的文档,但实际使用过程中坑还真不少,本文主要介绍Gorm进行数据操作完成前叙问题的主要过程,重点解决两个关键问题:Gorm中一对多表操作以及无固定数据库模型的操作方法。
2. 环境及表说明
Golang版本为:1.14.3 windows版
Gorm版本为V1.9.14
数据库为:PostgreSQL 10
实验中的表为:
如表示意图中所示,本问题中涉及三张表,记录项目基础信息的ProjectInfo表,记录各个项目需要采集属性字段的PropsToCollect表以及根据项目所需采集字段动态创建的XXXData表。三个表中ProjectInfo表中的ProjectName和PropsToCollect表中的ProjectNameRef为相互关联的外键。
3. 数据库连接
dbConnectStr:=fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s sslmode=disable", pgDBInfo.Host, pgDBInfo.Port, pgDBInfo.User, pgDBInfo.Name, pgDBInfo.Password)
DB, err = gorm.Open("postgres", dbConnectStr)
数据库连接过程中需要提供数据库IP、端口、用户名、数据库名、用户密码几个参数。
4. 一对多表模型定义
// PropsToCollect 用于存储工程需要采集的字段信息
type PropsToCollect struct {ProjectNameRef string //作为外键 如果在主表中没有指定associateForeignkey 那么必须为uint类型 不然就使用和associateForeignkey一致的字段类型Name string `gorm:"column:name" json:"name"`Label string `gorm:"column:label" json:"label"`DefaultValue string `gorm:"column:defualtvalue" json:"defaultValue"`
}// ProjectInfo 用于存储工程信息
type ProjectInfo struct { //这里不要用gorm.model 不然会自动加一个id 主键 导致association时出错 primary_key nilProjectName string `gorm:"column:projectname;primary_key;index;unique;not null" json:"projectName"`PropsToCollects []PropsToCollect `gorm:"ForeignKey:ProjectNameRef;AssociationForeignKey:ProjectName" json:"PropsToCollects"` //这种多个元素的字段 需要把字段名字该为xxxs因为gorm会自动把表名加上s
}
根据表设计定义表模型后,表会根据模型的关联关系被关联创建,数据的录入也会默认联动(删除好像不行)。该过程中需要注意几点:
- 一对多的模型写法:主表通过一个字段来记录一条记录中包含的多个关联记录,该字段一般为副表模型数组,如:ProjectInfo结构体中的PropsToCollects字段;且此处需要注意,如果没有对副表模型的表名特殊处理,此处的副表字段数组应该为XXXXs,因为Gorm默认会给表名加s,如果此处字段没有s结尾,两表关联不上。
- 关联键映射的写法:主表中的关联键需要标记ForeignKey和AssociationForeignKey,ForeignKey为关联表中的关联键,AssociationForeignKey为主表中的关联键,如本项目中,主表模型中的ForeignKey为ProjectnameRef,AssociationForeignKey为本模型中的ProjectName,注意这里的外键其实是逻辑外键,或者本文叫的关联键
- 不要在主表中使用Gorm中默认的模型参数。Gorm的表模型有个gorm.model可以自动定义自增长id,插入,修改以及删除字段,且该id为主键,如果在主表中引入了gorm的默认模型参数,那数据在入库的时候会报“association primary_key nil”的错
5. 不固定模型结构的表数据获取
本文不介绍不固定模型结构的表创建,因为……emm,我是通过Gorm执行原生SQL来创建的,非固定字段的表创建其实还比较容易,但是个人觉得获取未知字段的表数据还比较值得和大家分享下。
在本项目中因为知道某项目的数据记录表中的字段数和名字,且各个字段类型都为string所以能较好的设计读取的方法,这里我不再描述如何获取所有字段数的,直接贴如何获取数据的代码:
queryStr := "SELECT * from " + extrudeTable + " WHERE entityid = ?"rows, err := db.DB.Raw(queryStr, onePolygon.EntityID).Rows()
if err != nil {…
}var dest []interface{}
dest = append(dest, new(float32), new(float32)) //其他类型示例
for i := 0; i < len(propsToCollectInProject); i++ {dest = append(dest, new(string))
}
for rows.Next() { rows.Scan(dest...) //获取数据方法 *dest[i].(*string)
}
如代码所示,首先我用了Gorm来执行原生SQL进行查询,查询后的数据因为不知道具体的结构,所以采用interface{}数组来表达,每一个元素根据预知的类型进行初始化,然后从获取的原始数据中Scan到interface{}数组中,扫描出来的数据可以通过*dest[i].(*string)获取。
6. 小结
本文重点介绍了Gorm使用过程中一对多表的操作方法,以及在未知表结构的情况下如何从表查询结果中获取数据,该获取方法其实也适用于原生的sql包的查询结果。整体而言,在使用Gorm的过程中的感受是,该库的确能一定程度缓解一些固定范式表的操作,但是坑还是不少,且灵活性不足,所以个人在使用过程中还是将原生的SQL结合起来的;另外的一个问题是,该库写出来的代码和SQL的语句顺序不一样,长期写SQL的人可能觉得这语序怪怪的。
参考资料:
[1] https://eli.thegreenplace.net/2019/to-orm-or-not-to-orm/ 关于是否使用orm的思考
[2] https://gorm.io/docs/ grom官方文档
Gorm一对多关系表操作与非固定结构表数据获取相关推荐
- Django框架——模型层单表操作、模型层多表操作、模型层常用和非常用字段和参数、模型层进阶
文章目录 1 模型层-单表操作 一 ORM简介 二 单表操作 2.1 创建表 1 创建模型 2 更多字段 3 更多参数 4 settings配置 5 增加,删除字段 2.2 添加表纪录 2.3 查询表 ...
- mySQL主表与子表一对多关系,left join关联查询子表中其中一条记录
1.left join测试示例 SELECTa.id,a.create_name,a.create_time,b.id AS bId,b.charge_key,b.check_status FROMp ...
- mybatis多表操作(一对一、一对多、多对多)
1.获取主键值 1.1使用useGeneratedKeys属性 1.2使用selectKey标签 修改UserMapper 2.分页 3.多表操作(重难点) 3.1一对一 需求:(电商)[一个用户对应 ...
- 2019-7-27 [MySQL] DQL 简单查询[别名/去重/运算] 条件查询 排序查询 聚合查询 分组查询 导出与导入 多表操作[一对多/多对多][创外键 创联合主键 约束 添加 删除 测试]
文章目录 5 SQL语句(DQL) 5.1DQL准备工作和语法 5.1.1准备工作 5.1.2 DQL语法: 5.2 简单查询 5.2.1 查询所有的商品 5.2.2 查询商品名和商品价格. 5.2. ...
- MySQL学习笔记05【多表操作、三大范式、数据库的备份和还原】
MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...
- Django学习手册 - ORM 数据创建/表操作 汇总
ORM 查询的数据类型: QuerySet与惰性机制(可以看作是一个列表) 所谓惰性机制:表名.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它 ...
- DJango周总结二:模型层,单表,多表操作,连表操作,数据库操作,事务
django周复习二 1,模型层: 1单表操作: 13个必会操作总结 返回QuerySet对象的方法有 all() filter() exclude() ...
- Spring Data JPA多表操作(5)
Spring Data JPA多表操作(5) 数据库中多表之间的关系 多对多 一对多 一对一 一对多示例 数据库设计示例 实体示例 客户:指的是一家公司,我们记为A. 联系人:指的是A公司中的员工. ...
- MySQL-4多表操作
MySQL-4多表操作 文章目录 MySQL-4多表操作 多表关系 一对一 一对多/多对一 多对多 外键约束 介绍 特点 定义外键时,遵守下列规则 操作-创建外键约束 方式1-在创建表时设置外键约束 ...
最新文章
- 适合自学python的图书-有哪些适合零编程基础的人学习Python的书?
- [转] linux-Centos7安装python3并与python2共存
- 【网络编程】之八、异步选择WSAAsyncSelect
- Java IO: PipedInputStream
- 使用java程序对新浪微博的内容进行语义分析
- 用移位实现除以或者乘以一个数
- 编译linux tq2440,QT4.8.2在TQ2440开发板上的移植(一)--编译和安装
- 牛客网 [编程题]餐馆
- 字符串在JVM中如何存放 及常量池技术
- STM32F103ZET6【标准库函数开发】-----TM1638模块驱动4位8段共阴极数码管
- java 页眉页脚_Java 添加Word页眉、页脚
- 用8051单片机编程由P1.0和P1.1引脚分别输出周期为1ms和500us的方波
- Win7从文件服务器复制文件速度慢问题处理
- Python的第三次作业——陈灵院
- 黃綜翰:我的風羽路-新團隊新夢想
- 数据集仓库 —— UCI Machine Learning Repository
- JS 逆向的时候 Python 如何调用 JavaScript 代码?「建议收藏哦!」
- softlayer iso_在SoftLayer服务器上使用图形界面
- 放回c41_数学排列组合C41C43怎么算
- 【附源码】计算机毕业设计SSM社区养老院管理系统