Go 对象关系映射框架 GORM 使用示例

本贴最后更新于 1508 天前,其中的信息可能已经水流花落

前提条件

  • 安装 PostgreSql,创建好数据库(GORM 自动迁移表结构)
  • 安装 GoLandGo SDK
  • 获取 GORM:go get -u gorm.io/gorm
  • 获取 Postgres 驱动:go get -u gorm.io/driver/postgres

使用说明

  1. 复制本代码,打开 GoLand
  2. Ctrl + Shift + Alt + Insert 创建草稿文件
  3. 将代码粘贴到草稿文件中,修改数据库连接地址,按 Ctrl + Shift + F10 运行代码查看效果
package main import ( "database/sql" "encoding/json" "errors" "fmt" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" "gorm.io/gorm/schema" "log" "os" "strconv" "time" ) // 系统参数表结构体(实体类),GORM 约定参考: https://gorm.io/zh_CN/docs/conventions.html type TSysParam struct { // gorm.Model ID string `gorm:"type:varchar(32);not null;primaryKey;<-:create;comment:流水号参数唯一 ID"` DataTableName string `gorm:"type:varchar(128);<-;comment:数据库表名,如“t_sys_user”"` DataTableDescription string `gorm:"type:varchar(255);<-;comment:数据库表名(中文)说明信息"` SerialValue int `gorm:"size:32;<-;comment:流水号当前最大值"` SerialLength int `gorm:"size:32;<-;comment:流水号长度,不足前缀以“0”补齐"` Remark string `gorm:"type:varchar(1024);<-;comment:备注信息"` Enabled bool `gorm:"<-;default:true;comment:是否可用"` CreateTime *time.Time `gorm:"type:timestamptz;<-:create;autoCreateTime:milli;comment:创建时间"` CreateBy string `gorm:"type:varchar(32);<-:create;comment:创建人 ID,t_sys_user.id"` LastUpdateTime *time.Time `gorm:"type:timestamptz;<-;comment:最后修改时间"` LastUpdateBy string `gorm:"type:varchar(32);<-;comment:最后修改人 ID,t_sys_user.id"` } // 为 TSysParam 结构体实现获取表名方法,单独设置 TSysParam 结构体的表名为 `t_sys_param`,未配置全局禁用复数表名时可使用此方法 //func (TSysParam) TableName() string { // return "t_sys_param" //} // GORM 参考文档: https://gorm.io/zh_CN/docs/ func main() { initDbConn() // CRUD 示例 createExample() readExample() updateExample() deleteExample() printStats() } // GORM 数据库定义 var GormDB *gorm.DB // 连接池数据库句柄 var SqlDB *sql.DB // 错误信息 var err error // 初始化数据库连接 func initDbConn() { GormDB, err = gorm.Open(postgres.New(postgres.Config{ // 通过一个现有的数据库连接来初始化,无需使用 DSN // Conn: SqlDB, // 数据源名称 DSN: "host=192.168.1.1 port=5432 user=test password=test dbname=db_test sslmode=disable TimeZone=Asia/Shanghai", // 禁用隐式预处理语句 PreferSimpleProtocol: true, }), &gorm.Config{ // 日志配置 Logger: getLogger(), // 自定义命名策略 NamingStrategy: schema.NamingStrategy{ // 全局使用单数表,禁止自动转换为复数形式表名 SingularTable: true, }, // 插入数据默认批处理大小 CreateBatchSize: 1000, }) if err != nil { panic("数据库连接失败!") } // 数据库连接池 SqlDB, err = GormDB.DB() if err != nil { panic("数据库连接池获取失败!") } // 设置空闲连接池中连接的最大数量 SqlDB.SetMaxIdleConns(10) // 设置打开数据库连接的最大数量 SqlDB.SetMaxOpenConns(1e3) // 设置连接可复用的最大时间 SqlDB.SetConnMaxLifetime(time.Hour) printStats() // 自动迁移给定模型为数据库表结构,未创建表或需要修改表结构的情况下可以启用 // _ = GormDB.AutoMigrate(&TSysParam{}) } // 获取当前时间指针 func nowTime() *time.Time { now := time.Now() return &now } // 添加数据,参考 https://gorm.io/zh_CN/docs/create.html func createExample() { // 添加单条数据 sysParam := TSysParam{ ID: "test_001", DataTableName: "test_table", DataTableDescription: "测试表", SerialValue: 0, SerialLength: 10, Enabled: true, CreateBy: "00000", CreateTime: nowTime(), } result := GormDB.Create(&sysParam) printData(&sysParam, result, "Create") // 向指定(Select)字段中保存数据,忽略未指定的字段(NULL) sysParam = TSysParam{ ID: "test_002", DataTableName: "test_table_002", DataTableDescription: "测试表", SerialValue: 0, SerialLength: 10, Enabled: true, CreateBy: "00000", } result = GormDB. Select("ID", "DataTableName", "DataTableDescription", "SerialValue", "SerialLength"). Create(&sysParam) printData(&sysParam, result, "Create") // 添加多条数据 dataSize := 3 sysParams := make([]TSysParam, dataSize) for i := 0; i < dataSize; i++ { index := strconv.Itoa(i) sysParams[i] = TSysParam{ ID: "test_list_" + index, DataTableName: "test_table_" + index, DataTableDescription: "测试表_" + index, SerialValue: 0, SerialLength: 10, Enabled: true, CreateBy: "00000", } } // 未配置全局 CreateBatchSize 参数的情况下,一次性批量保存全部数据 result = GormDB.Create(&sysParams) // 指定单次批量保存的条数分批保存,每循环到 batchSize 条保存一次直至全部完成,保存大量数据可用此方法分批保存 // result = GormDB.CreateInBatches(&sysParams, dataSize) printData(&sysParams, result, "Create", "(batch)") } // 查询数据,参考 https://gorm.io/zh_CN/docs/query.html https://gorm.io/zh_CN/docs/advanced_query.html func readExample() { var sysParam *TSysParam // 根据主键查询单条数据,默认根据主键正序排序 result := GormDB.First(&sysParam, "00001") printData(sysParam, result, "First") sysParam = nil // 根据自定义条件查询最后一条数据,默认根据主键倒序排序 result = GormDB.Last(&sysParam, "enabled = ?", false) printData(sysParam, result, "Last") sysParam = nil // 获取一条数据,未指定排序字段 result = GormDB.Take(&sysParam, "create_by = ?", "00000") printData(sysParam, result, "Take") sysParam = nil // 不使用结构体查询,直接使用表名 result = GormDB.Table("t_sys_param").First(&sysParam) printData(sysParam, result, "Table", "First") sysParam = nil // 查询全部 sysParams := new([]TSysParam) result = GormDB.Find(&sysParams, "enabled = ?", true) // 查询可用数据 // result = GormDB.Find(&sysParams, "enabled = ?", true) printData(&sysParams, result, "Find", "(all)") // 按 AND 条件查询多条 sysParams = new([]TSysParam) result = GormDB.Find(&sysParams, TSysParam{Enabled: true, CreateBy: "00000"}) // 不使用结构体,直接使用字段 Map // result = GormDB.Find(&sysParams, map[string]interface{}{"enabled": true, "create_by": "00000"}) printData(&sysParams, result, "Find", "(AND)") // 按 OR 条件查询多条 sysParams = new([]TSysParam) result = GormDB.Where("enabled", true).Or("create_by", "00000").Find(&sysParams) printData(&sysParams, result, "Find", "(OR)") // 按 IN 条件查询多条 sysParams = new([]TSysParam) result = GormDB.Find(&sysParams, "id IN ?", []string{"00001", "00002"}) printData(&sysParams, result, "Find", "(IN)") // 按 NOT 条件查询多条 sysParams = new([]TSysParam) result = GormDB.Not("serial_value", 0).Find(&sysParams) printData(&sysParams, result, "Find", "(NOT)") // 分页排序查询指定字段 sysParams = new([]TSysParam) allSysParams := new([]TSysParam) result = GormDB. // 每页 5 条,第二页 Offset(5).Limit(5). Order("serial_value DESC, id"). Select("data_table_name", "serial_value", "serial_length"). Find(&sysParams) printData(&sysParams, result, "Find", "(select-order-paging)") // 消除分页,获取全部 unpageResult := result.Offset(-1).Limit(-1).Find(&allSysParams) // 总条数 pagingResult.RowsAffected printData(&allSysParams, unpageResult, "Find", "(select-order-paging-all)") } // 修改数据,参考 https://gorm.io/zh_CN/docs/update.html func updateExample() { sysParam := TSysParam{ ID: "test_001", // 根据主键修改指定数据 DataTableName: "test_table_001", DataTableDescription: "测试表-001", SerialValue: 1, SerialLength: 10, Enabled: true, CreateTime: nowTime(), // CreateTime 和 CreateBy 已在标签中配置为可读、可创建、不可修改 CreateBy: "00001", LastUpdateTime: nowTime(), LastUpdateBy: "00000", } // 更新所有字段,包含零值 result := GormDB.Save(&sysParam). // 查询修改结果重新赋值给 sysParam Find(&sysParam) printData(&sysParam, result, "UPDATE", "Save") // 更新单个字段 result = GormDB.Model(&sysParam). Where("enabled", true). Update("serial_value", sysParam.SerialValue+1). Find(&sysParam) printData(&sysParam, result, "UPDATE", "Model", "WhereUpdate") // 更新多个字段,使用结构体只会更新非零值字段,要更新零值字段需要使用 Select 指定要修改的字段,或者直接使用 Select("*") 更新全部字段 sysParam = TSysParam{ ID: "test_001", // 根据主键修改指定数据 SerialValue: sysParam.SerialValue + 1, SerialLength: 10, Enabled: false, // false 为 GORM Model 结构体零值,不会修改此字段 LastUpdateTime: nowTime(), LastUpdateBy: "00000", } result = GormDB.Model(&sysParam). Where("enabled", true). Updates(&sysParam). Find(&sysParam) printData(&sysParam, result, "UPDATE", "Model", "Updates") // 使用 map 可修改零值字段 result = GormDB.Model(&sysParam). Updates(map[string]interface{}{"serial_value": sysParam.SerialValue + 1, "enabled": false}). Find(&sysParam) printData(&sysParam, result, "UPDATE", "Model", "UpdatesMap") // 使用 Omit 忽略更新指定字段 result = GormDB.Model(&sysParam). Omit("serial_value"). Updates(map[string]interface{}{"serial_value": sysParam.SerialValue + 1, "enabled": true}). Find(&sysParam) printData(&sysParam, result, "UPDATE", "Model", "UpdatesOmit") } // 删除数据,参考 https://gorm.io/zh_CN/docs/delete.html func deleteExample() { // !!! 注意,删除数据时如果未指定主键或其他条件,将会触发无条件的批量删除 sysParam := TSysParam{ ID: "test_002", // 主键 } // 根据主键删除指定数据 result := GormDB.Delete(&sysParam) sysParam = TSysParam{} result.Find(&sysParam) printData(&sysParam, result, "Delete") // 通过复合条件删除数据 result = GormDB.Where("id LIKE ? AND data_table_name LIKE ?", "test_%", "test_table_%"). Delete(&sysParam). Find(&sysParam) printData(&sysParam, result, "DeleteWhere") } // 获取 GORM 日志接口 func getLogger() logger.Interface { gormLogger := logger.New( // io writer log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ // 慢 SQL 阈值 SlowThreshold: 3 * time.Second, // 日志级别 LogLevel: logger.Info, // 是否启用彩色打印 Colorful: true, }, ) return gormLogger } // 打印数据 func printData(sysParam interface{}, result *gorm.DB, morInfo ...interface{}) { jsonByte, _ := json.Marshal(&sysParam) result.Logger.Info(nil, string(jsonByte)) fmt.Println("条数:", result.RowsAffected, "\t错误信息:[", result.Error, "]\t是否为无记录错误:", errors.Is(result.Error, gorm.ErrRecordNotFound)) if len(morInfo) > 0 { fmt.Println(morInfo) } } // 打印数据库统计信息 func printStats() { dbStats := SqlDB.Stats() jsonByte, _ := json.Marshal(dbStats) fmt.Println(string(jsonByte)) /*fmt.Printf(` 空闲连接数: %d 使用中的连接数: %d 由于达到设置的空闲连接池的最大数量而关闭的连接数: %d 由于达到设置的连接可空闲的最长时间而关闭的连接数: %d 由于达到设置的可重用连接的最长时间而关闭的连接数: %d 数据库的最大打开连接数: %d 等待的连接总数: %d 等待新连接被阻止的总时间: %d`, dbStats.Idle, dbStats.InUse, dbStats.MaxIdleClosed, dbStats.MaxIdleTimeClosed, dbStats.MaxLifetimeClosed, dbStats.MaxOpenConnections, dbStats.WaitCount, dbStats.WaitDuration)*/ }
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    498 引用 • 1395 回帖 • 257 关注
  • GORM
    8 引用 • 19 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
iTanken
飘风不终朝,骤雨不终日。 成都

推荐标签 标签

  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    143 引用 • 442 回帖
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 5 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    245 引用 • 1338 回帖
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 647 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 546 关注
  • sts
    2 引用 • 2 回帖 • 224 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖 • 3 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 28 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 23 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 416 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖 • 3 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 633 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 9 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    66 引用 • 114 回帖 • 201 关注
  • Anytype
    3 引用 • 31 回帖 • 12 关注
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    31 引用 • 96 回帖
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 442 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 33 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 75 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 55 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 735 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 1 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2040 回帖
  • Word
    13 引用 • 40 回帖
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 2 关注