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

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

前提条件

  • 安装 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 回帖 • 252 关注
  • GORM
    8 引用 • 19 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    63 引用 • 289 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • GitLab

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

    46 引用 • 72 回帖 • 1 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 649 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 644 关注
  • WebComponents

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

    1 引用 • 15 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    89 引用 • 1251 回帖 • 393 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 1 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖 • 1 关注
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 119 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    125 引用 • 74 回帖
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖
  • 电影

    这是一个不能说的秘密。

    123 引用 • 608 回帖
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    92 引用 • 752 回帖 • 2 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 17 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 712 关注
  • Latke

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

    71 引用 • 535 回帖 • 830 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 279 关注
  • etcd

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

    6 引用 • 26 回帖 • 546 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 643 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖 • 1 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    183 引用 • 3885 回帖
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 78 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    187 引用 • 832 回帖