目录

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
}

根据表设计定义表模型后,表会根据模型的关联关系被关联创建,数据的录入也会默认联动(删除好像不行)。该过程中需要注意几点:

  1. 一对多的模型写法:主表通过一个字段来记录一条记录中包含的多个关联记录,该字段一般为副表模型数组,如:ProjectInfo结构体中的PropsToCollects字段;且此处需要注意,如果没有对副表模型的表名特殊处理,此处的副表字段数组应该为XXXXs,因为Gorm默认会给表名加s,如果此处字段没有s结尾,两表关联不上。
  2. 关联键映射的写法:主表中的关联键需要标记ForeignKey和AssociationForeignKey,ForeignKey为关联表中的关联键,AssociationForeignKey为主表中的关联键,如本项目中,主表模型中的ForeignKey为ProjectnameRef,AssociationForeignKey为本模型中的ProjectName,注意这里的外键其实是逻辑外键,或者本文叫的关联键
  3. 不要在主表中使用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一对多关系表操作与非固定结构表数据获取相关推荐

  1. Django框架——模型层单表操作、模型层多表操作、模型层常用和非常用字段和参数、模型层进阶

    文章目录 1 模型层-单表操作 一 ORM简介 二 单表操作 2.1 创建表 1 创建模型 2 更多字段 3 更多参数 4 settings配置 5 增加,删除字段 2.2 添加表纪录 2.3 查询表 ...

  2. 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 ...

  3. mybatis多表操作(一对一、一对多、多对多)

    1.获取主键值 1.1使用useGeneratedKeys属性 1.2使用selectKey标签 修改UserMapper 2.分页 3.多表操作(重难点) 3.1一对一 需求:(电商)[一个用户对应 ...

  4. 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. ...

  5. MySQL学习笔记05【多表操作、三大范式、数据库的备份和还原】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  6. Django学习手册 - ORM 数据创建/表操作 汇总

    ORM 查询的数据类型: QuerySet与惰性机制(可以看作是一个列表) 所谓惰性机制:表名.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它 ...

  7. DJango周总结二:模型层,单表,多表操作,连表操作,数据库操作,事务

    django周复习二  1,模型层:   1单表操作:    13个必会操作总结     返回QuerySet对象的方法有     all()     filter()     exclude()   ...

  8. Spring Data JPA多表操作(5)

    Spring Data JPA多表操作(5) 数据库中多表之间的关系 多对多 一对多 一对一 一对多示例 数据库设计示例 实体示例 客户:指的是一家公司,我们记为A. 联系人:指的是A公司中的员工. ...

  9. MySQL-4多表操作

    MySQL-4多表操作 文章目录 MySQL-4多表操作 多表关系 一对一 一对多/多对一 多对多 外键约束 介绍 特点 定义外键时,遵守下列规则 操作-创建外键约束 方式1-在创建表时设置外键约束 ...

最新文章

  1. Python基础教程:属性值设置和判断变量是否存在
  2. C#代码创建Xml文件
  3. 日期选择控件-laydate
  4. uniapp苹果底部栏自适应配置
  5. IDEA的Debug 控制台输出窗口没有显示
  6. 【51CTO/BBS】请教: SQL里有没有字符串分解Split的函数??
  7. 开源监控软件 Hyperic 的两种插件
  8. matlab拟合模型学习总结
  9. WinRAR 5.40无弹窗广告注册版下载
  10. 论文查重不能超过多少?
  11. (附源码)APP+spring boot心理健康线上咨询系统 毕业设计 031539
  12. Zotero BookxNote
  13. 【防坑指南】nginx重启后出现[error] open() “/usr/local/var/run/nginx/nginx.pid” failed
  14. linux垃圾清理总结(超实用)
  15. vue里的axios获取本地的json数据
  16. Shell 变量嵌套
  17. java http 用户名密码_Web后端语言模拟http请求(带用户名和密码)实例代码大全
  18. 游戏自评——英雄无敌手游
  19. 收音机c语言程序,基于单机收音机的C语言程序.doc
  20. 世界七大高校人工智能实验室研究方向网址入口

热门文章

  1. 硬件I2C sht3x温湿度传感器 学习过程记录
  2. 慢慢毁掉你的,是你的将就与凑合
  3. NSAT-2000晶体管自动化测试系统
  4. 图片标签img和超链接标签a
  5. sqlite3.OperationalError: near “(“: syntax error
  6. 遥感图像怪谈之一-----------华北平原秋季的神秘色彩
  7. AutoSAR系列讲解(实践篇)12.1-Diagnostics简介
  8. 如何避免危险的免费wifi?
  9. java搭建简单web服务器用于WiFi模块发送指令
  10. Kmplayer 播放器将屏幕旋转的方法