目录

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的图书-有哪些适合零编程基础的人学习Python的书?
  2. [转] linux-Centos7安装python3并与python2共存
  3. 【网络编程】之八、异步选择WSAAsyncSelect
  4. Java IO: PipedInputStream
  5. 使用java程序对新浪微博的内容进行语义分析
  6. 用移位实现除以或者乘以一个数
  7. 编译linux tq2440,QT4.8.2在TQ2440开发板上的移植(一)--编译和安装
  8. 牛客网 [编程题]餐馆
  9. 字符串在JVM中如何存放 及常量池技术
  10. STM32F103ZET6【标准库函数开发】-----TM1638模块驱动4位8段共阴极数码管
  11. java 页眉页脚_Java 添加Word页眉、页脚
  12. 用8051单片机编程由P1.0和P1.1引脚分别输出周期为1ms和500us的方波
  13. Win7从文件服务器复制文件速度慢问题处理
  14. Python的第三次作业——陈灵院
  15. 黃綜翰:我的風羽路-新團隊新夢想
  16. 数据集仓库 —— UCI Machine Learning Repository
  17. JS 逆向的时候 Python 如何调用 JavaScript 代码?「建议收藏哦!」
  18. softlayer iso_在SoftLayer服务器上使用图形界面
  19. 放回c41_数学排列组合C41C43怎么算
  20. 【附源码】计算机毕业设计SSM社区养老院管理系统

热门文章

  1. 人工智能概览及AI数学基础
  2. 蓝桥杯倒计时 | 倒计时6天
  3. Hadoop MapReduce编程模型
  4. eplan连接定义点不显示_最新电气绘图软件EPLAN,附超详细安装教程
  5. Wex5----错误收集
  6. 毕节计算机考试准考证打印,2016年9月毕节计算机三级四级准考证打印入口,计算机等级考试时间查询...
  7. 组装电脑基础知识之电源
  8. 金蝶KIS专业版销售出库反审核不成功,销售订单关联的出库数量为负!
  9. 怎么在手机上预览和测试web项目
  10. 黑马程序员——99乘法表