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

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

前提条件

  • 安装 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 发布的第二款编程语言。

    500 引用 • 1396 回帖 • 246 关注
  • GORM
    8 引用 • 19 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 271 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    440 引用 • 1238 回帖 • 593 关注
  • Laravel

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

    19 引用 • 23 回帖 • 737 关注
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    79 引用 • 431 回帖
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    172 引用 • 534 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖 • 1 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 826 关注
  • ngrok

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

    7 引用 • 63 回帖 • 654 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖 • 2 关注
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    34 引用 • 37 回帖 • 557 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    188 引用 • 319 回帖 • 240 关注
  • WordPress

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

    46 引用 • 114 回帖 • 167 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 818 回帖 • 1 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 179 关注
  • danl
    176 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 379 关注
  • Access
    1 引用 • 3 回帖 • 3 关注
  • OneNote
    1 引用 • 3 回帖
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    115 引用 • 318 回帖
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 764 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 82 关注
  • abitmean

    有点意思就行了

    34 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 406 关注
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 561 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    10061 引用 • 45719 回帖 • 67 关注