【Gorm】模型定义

intro

package mainimport ("gorm.io/gorm""gorm.io/driver/sqlite" // GORM 使用该驱动来连接和操作 SQLite 数据库。
)type Product struct {gorm.Model //  嵌入GORM 内置的模型结构,包含 ID、CreatedAt、UpdatedAt、DeletedAt 四个字段Code  stringPrice uint
}func main() {db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) // 使用 SQLite 驱动打开名为 "test.db" 的数据库文件,并用默认配置初始化 GORMif err != nil {panic("failed to connect database")}// 迁移 schemadb.AutoMigrate(&Product{}) // 根据 Product 结构体自动创建或更新数据库中的表结构,确保数据表与结构体一致。// Create 在数据库中插入一条新记录db.Create(&Product{Code: "D42", Price: 100})// Readvar product Product // 用来存储查询结果db.First(&product, 1) // 根据整型主键查找db.First(&product, "code = ?", "D42") // 通过条件查找,查找 code 字段值为 D42 的记录// Update - 将 product 的 price 更新为 200db.Model(&product).Update("Price", 200)// Update - 更新多个字段// 使用结构体 Product 作为参数更新多个字段,此方式只会更新结构体中非零值的字段。db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // 仅更新非零值字段// 使用 map 更新字段,可以同时更新多个字段,不受非零值的限制db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})// Delete - 删除 productdb.Delete(&product, 1)
}
  • gorm.Config{}:这是一个结构体字面量,用于创建一个 gorm.Config 类型的实例,其中的各个字段都被赋予了默认的零值(如果没有显式指定)。
  • & 运算符:在结构体字面量前加 &,表示取这个实例的地址,也就是生成一个指向 gorm.Config 实例的指针。
  • 传递指针而非值,可以使函数 gorm.Open 修改或读取配置,同时也避免了结构体值的拷贝。

数据库迁移(schema migration)

  • 定义:数据库迁移是指对数据库表结构进行创建、修改或删除的过程。
  • 自动迁移:GORM 提供了 AutoMigrate 方法,可以根据你的 Go 结构体(模型)自动创建或更新数据库中的表结构。
    • 示例:db.AutoMigrate(&User{}) 会检查 User 模型,并自动生成或调整表结构来匹配这个模型。
  • 优点
    • 让你无需手动编写 SQL 语句来创建或修改表结构。
    • 保证模型和数据库结构保持一致。
  • 局限性
    • 对于复杂的结构变更(如大规模数据迁移、索引优化等),可能需要手动编写迁移脚本。

结构体标签和反射

  • 结构体标签:了解 Go 中标签的语法和使用场景,特别是如何利用标签为字段添加元信息。

    • 概念:在 Go 中,你可以在结构体字段后面加上反引号(```)内的标签,这些标签是一些字符串,用来存储额外的信息。
    • 用途
      • 用于告诉 GORM 如何将这个字段映射到数据库中的列,比如指定列名、数据类型、约束条件等。
      • 也常见于 JSON 序列化,告诉程序如何将字段转换为 JSON 格式。
    type User struct {Name  string `gorm:"column:user_name;type:varchar(100);not null" json:"name"`Email string `gorm:"unique;not null" json:"email"`
    }
    // Name 字段在数据库中将映射为 user_name 列,类型为 varchar(100) 且不能为空
    // 同时在 JSON 中使用 name 作为键
    
  • 反射机制:虽然不必深入,但需要了解反射是如何在运行时读取结构体标签并据此执行操作的。

    • 反射是 Go 语言的一种特性,它允许程序在运行时检查变量的类型、结构以及标签等信息。

    • 用途

      • GORM 就是通过反射读取结构体标签,从而了解如何把结构体字段和数据库表的列对应起来。
      • 反射可以动态地获取类型信息,使得代码更灵活,但同时也会带来一定的性能开销。
      import ("fmt""reflect"
      )type User struct {Name string `gorm:"column:user_name" json:"name"`
      }func main() {user := User{Name: "Alice"}t := reflect.TypeOf(user)field, _ := t.FieldByName("Name")fmt.Println("GORM标签:", field.Tag.Get("gorm"))fmt.Println("JSON标签:", field.Tag.Get("json"))
      }

      这段代码利用反射获取了 User 结构体中 Name 字段的 gormjson 标签信息。

time.Time 的基本用法和常见操作

GORM 会自动处理时间戳字段。

获取当前时间:now := time.Now()// 使用 Format 方法将时间转换为字符串
formatted := now.Format("2006-01-02 15:04:05")// 使用 time.Parse 将字符串转换为 time.Time 类型
t, err := time.Parse("2006-01-02", "2025-04-06")// 比较时间:可以使用 Before、After、Equal 等方法比较两个时间的先后。

模型定义

模型定义

  • 映射机制:GORM 将 Go 语言中的结构体(struct)映射为数据库中的表。定义模型就是编写对应的结构体。
  • 字段类型:模型字段可以使用基本类型(如 uintstringuint8)、指针(如 *string*time.Time)以及特殊类型(如 sql.NullStringsql.NullTime)来处理可空值
  • 自动管理的时间戳:如果定义了 CreatedAtUpdatedAt 字段,GORM 会在创建和更新记录时自动填充当前时间。
  • 非导出字段:结构体中首字母小写的字段不会映射到数据库中。

内置模型(gorm.Model)

  • GORM 提供了预定义结构体 gorm.Model,包含了常用的字段:
    • ID(主键)
    • CreatedAt(创建时间)
    • UpdatedAt(更新时间)
    • DeletedAt(软删除字段,支持索引)
  • 嵌入 gorm.Model 可以让你快速拥有一套标准的字段。

约定与自动行为

  • 主键约定:默认使用名为 ID 的字段作为主键。

  • 表名和列名:GORM 会自动将结构体名转换为 snake_case 的复数形式(例如 User 变为表名 users),而字段名也转换为 snake_case。

  • 自动时间戳:除了自动填充 CreatedAtUpdatedAt 外,还支持通过标签(如 autoCreateTimeautoUpdateTime)自定义时间精度(秒、毫秒、纳秒)。

    type User struct {CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充Updated   int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳纳秒数填充更新时间Updated   int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间Created   int64 `gorm:"autoCreateTime"`      // 使用时间戳秒数填充创建时间
    }
    

标签和字段配置

  • 字段级控制:使用标签可以设置字段的数据库列名、数据类型、大小、默认值以及约束(如非空、唯一、索引等)。

    type Product struct {ID          uint   `gorm:"primaryKey"`                                   // 主键字段Code        string `gorm:"column:product_code;type:varchar(100);not null;unique;index"` // 指定列名为 product_code,数据类型为 varchar(100),非空、唯一并创建索引Price       uint   `gorm:"default:0;not null"`                           // 默认值为 0,且不允许为空Description string `gorm:"type:text;default:'no description'"`           // 指定数据类型为 text,并设置默认描述
    }
    • column:将 Code 字段映射到数据库的 product_code 列。
    • type:设置数据库中的数据类型。
    • not null、unique、index:添加非空、唯一和索引约束。
    • default:指定默认值。
  • 权限控制:标签还支持配置字段在 CRUD 操作中的读写权限(例如只创建、只更新或完全忽略)。

    type User struct {Name string `gorm:"<-:create"` // 允许读和创建Name string `gorm:"<-:update"` // 允许读和更新Name string `gorm:"<-"`        // 允许读和写(创建和更新)Name string `gorm:"<-:false"`  // 允许读,禁止写Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)Name string `gorm:"->;<-:create"` // 允许读和写Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)Name string `gorm:"-"`  // 通过 struct 读写会忽略该字段Name string `gorm:"-:all"`        // 通过 struct 读写、迁移会忽略该字段Name string `gorm:"-:migration"`  // 通过 struct 迁移会忽略该字段
    }
    
    • 理解箭头方向

      • <- 表示写入(写操作)

        数据从外部传入数据库时走 <-。(意味着在写入操作(无论创建或更新)时允许该字段参与。)

      • -> 表示读取(读操作)

        数据从数据库中输出时走 ->。(意味着在读取操作时允许该字段参与。)

    • 后缀部分(如 :create:updatefalse)用于进一步限制操作时机:

      • <-[操作] 限定写入操作
        • <-:create仅在创建时写入,更新时不允许写入。
        • <-:update仅在更新时写入,创建时不允许写入。
        • <-创建和更新都允许写入
        • <-:false禁止写入,相当于只读。
      • >[操作] 限定读取操作
        • >只允许读取(写入禁止)。
        • >:false禁止读取(但可能允许写入,具体配合 <- 说明)。
    • 组合写法

      • >;<-:create读取始终允许,但写入仅在创建时允许;更新时不能写。
      • >:false;<-:create禁止从数据库中读取>:false),但在创建时可以写入。
    • 忽略字段的写法

      • "-":完全忽略该字段,既不读也不写。
      • "-:all":在所有操作(读、写、迁移)中都忽略。
      • "-:migration":仅在迁移操作时忽略该字段。
  • 嵌入结构体:通过匿名嵌入或使用 embedded 标签,可以将一个结构体的字段直接嵌入到父结构体中,并且可以用 embeddedPrefix 添加前缀。

    type Address struct {City  stringState string
    }type Customer struct {ID   uint   `gorm:"primaryKey"`Name string// 匿名嵌入 Address 结构体,其字段会直接映射到 Customer 表中Address// 使用 embedded 标签嵌入 Address 结构体,并添加前缀 contact_Contact Address `gorm:"embedded;embeddedPrefix:contact_"`
    }

高级选项

  • 除了基础的映射和约定,GORM 允许使用序列化标签(serializer)来自定义数据的存储和读取方式,增强灵活性。
  • 对于字段更新的细粒度控制,如仅更新非零值字段、使用 map 或结构体进行批量更新,均由标签和方法调用来实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75907.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言从专家到小白

文章目录 下载安装R下载安装R StudioCRAN 下载安装R Index of /bin https://cran.r-project.org/ 下载安装R Studio https://posit.co/download/rstudio-desktop/ CRAN R综合档案网络。 CRAN 镜像是一个提供 R 语言软件和包的在线服务&#xff0c;用户可以从不同的地区选择…

Java的Selenium的特殊元素操作与定位之时间日期控件

分为两种情况: 控件没有限制手动输入&#xff0c;则直接调用sendKeys方法写入时间数据 //时间日期控件处理 chromeDriver.get ("https://www,fliggy,com/?ttidsem.000000736&hlreferidbaidu.082076&route sourceseo"); chromeDriver.findElement (By.xpat…

38常用控件_QWidget的enable属性(2)

实现用另一个按钮切换之前按钮的“可用”状态 在同一个界面中,要求不同的控件的 objectName 也是必须不同的.(不能重复&#xff09; 后续就可以通过 ui->objectName 方式来获取到对应的控件对象了 ui->pushButton // 得到了第一个按钮对应的对象 ui->pushButton 2 //…

【Linux学习笔记】初识进程概念和进程PCB

【Linux学习笔记】初识冯诺依曼体系和进程PCB &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 文章目录 【Linux学习笔记】初识冯诺依曼体系和进程PCB前言一. 冯诺依曼体系结构1.1 关于冯诺依曼体系的要点&#xff1a; 二. 操…

7.3 主成分分析(PCA)

一、协方差矩阵 这节是介绍 SVD 在统计和数据分析中的一个主要应用&#xff0c;即主成分分析。例子来自于人类的基因组&#xff0c;脸部识别和金融&#xff0c;目的是理解一个大的数据矩阵&#xff08;测量值&#xff09;。对于 n n n 个样本&#xff0c;我们每个测量 m m m…

anaconda安装使用+pytorch环境配置(cpu)+pycharm环境配置(详细教程)

一、anaconda下载 1.anaconda官网尝试下载&#xff1a; 官网网址&#xff1a;Anaconda | Built to Advance Open Source AI 1.进入官网 2.点击Products->Distribution&#xff0c;跳过注册进入下载页面 3.选择系统下载 2.清华镜像下载 1.网址&#xff1a;Index of /anac…

Unity3D仿星露谷物语开发34之单击Drop项目

1、目标 当在道具栏中选中一个Item时&#xff0c;点击地面就可以实现Item的drop操作&#xff0c;每点击一次就drop一次&#xff0c;直到道具栏中Item数量不够。 这样的好处&#xff1a;避免每次Drop都从道具栏中拖拉Item&#xff0c;通过点击这种操作可以更加高效。 方法&am…

java 正则表达式优化

1&#xff0c;什么是正则表达式 正则表达式使用一些特定的元字符来检索、匹配以及替换符合规则的字符串。 构造正则表达式语法的元字符&#xff0c;由普通字符、标准字符、限定字符&#xff08;量词&#xff09;、定位字符&#xff08;边界字符&#xff09;组成 普通字符 字母[…

检测链表是否有环, 动画演示, Floyd判圈算法扩展应用

力扣原题链接: 141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 哈希表 检测环形链表, 直观的思路就是使用哈希表, 遍历这个链表, 将访问过的节点加入到哈希表中, 如果遍历过程中发现节点已经存在于哈希表中, 则说明链表有环. 复杂度分析: 时间复杂度: O(N), 最坏情…

linux专题3-----linux上链接远程mysql

要在 Ubuntu 上连接远程 MySQL 数据库&#xff0c;你可以使用 MySQL 客户端工具或者其他数据库管理工具&#xff0c;如 phpMyAdmin 或 MySQL Workbench。以下是使用 MySQL 命令行工具连接远程 MySQL 的步骤&#xff1a; 确保已安装 MySQL 客户端 首先&#xff0c;确保你的 Ub…

webpack js 逆向 --- 个人记录

网站 aHR0cDovL2FlcmZheWluZy5jb20v加密参数 参数加密位置 方法&#xff1a; 1. 构造自执行函数 !function(e) {// 加载器 }(// 模块1&#xff1b;// 模块2 )2. 找到js的加载器 3. 把上述代码放入第一步构造的自执行函数(完整扣取一整个加载器里的代码)&#xff0c;并用一…

用HTML.CSS.JavaScript实现一个贪吃蛇小游戏

目录 一、引言二、实现思路1. HTML 结构2. CSS 样式3. JavaScript 逻辑 三、代码实现四、效果展示 一、引言 贪吃蛇是一款经典的小游戏&#xff0c;曾经风靡一时。今天&#xff0c;我们将使用 HTML、CSS 和 JavaScript 来实现一个简单的贪吃蛇小游戏。通过这个项目&#xff0c…

基于α-β剪枝的含禁手AI五子棋

前言&#xff1a; 正常的五子棋应当设有禁手规则&#xff0c;否则先手黑棋必赢&#xff0c;基于此点设计出一款包含禁手的AI五子棋项目&#xff0c;该项目代码已在github开源&#xff0c;感兴趣的友友可以自取试玩:ace-trump-tech/AI-Gomoku-with-Prohibition-Moves: 含禁手的A…

Spring Boot 集成 Redis中@Cacheable 和 @CachePut 的详细对比,涵盖功能、执行流程、适用场景、参数配置及代码示例

以下是 Cacheable 和 CachePut 的详细对比&#xff0c;涵盖功能、执行流程、适用场景、参数配置及代码示例&#xff1a; 1. 核心对比表格 特性CacheableCachePut作用缓存方法的返回结果&#xff0c;避免重复计算执行方法并更新缓存&#xff0c;不覆盖原有缓存执行流程缓存命中…

可以使用费曼学习法阅读重要的书籍

书本上画了很多线&#xff0c;回头看等于没画出任何重点。 不是所有的触动都是有效的。就像你曾经看过很多好文章&#xff0c;当时被触动得一塌糊涂&#xff0c;还把它们放进了收藏夹&#xff0c;但一段时间之后&#xff0c;你就再也记不起来了。如果让你在一本书上画出令自己…

Nginx之https重定向为http

为了将Nginx中443端口的请求重定向到80端口&#xff0c;你可以按照以下步骤进行操作&#xff1a; ‌确认Nginx已经正确安装并运行‌&#xff1a; 确保Nginx服务已经在你的系统上安装并运行。你可以通过运行以下命令来检查Nginx的状态&#xff08;具体命令可能因操作系统而异&a…

【ARTS】【LeetCode-2873】有序三元组中的最大值!

前言 仅做学习使用&#xff0c;侵删 什么是ARTS&#xff1f; 算法(Algorithm): 每周至少一道LeetCode算法题&#xff0c;加强编程训练和算法学习 阅读(Review)&#xff1a; 阅读并点评至少一篇英文技术文章&#xff0c;提高英文水平 技巧 (Tip)&#xff1a;学习至少一个技…

基于spring boot 鲜花销售系统PPT(源码+lw+部署文档+讲解),源码可白嫖!

课题意义 随着网络不断的普及发展&#xff0c;鲜花销售系统依靠网络技术的支持得到了快速的发展&#xff0c;首先要从用户的实际需求出发&#xff0c;通过了解用户的需求开发出具有针对性的信息管理系统&#xff0c;利用目前网络给用户带来的方便快捷这一特点对系统进行调整&am…

Redis常用的数据结构及其使用场景

字符串(String) string 是 redis 最基本的类型&#xff0c;你可以理解成与 Memcached 一模一样的类型&#xff0c;一个 key 对应一个 value。 string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据&#xff0c;比如jpg图片或者序列化的对象。 string 类型是 R…

设计模式简述(五)建造者模式

建造者模式 描述基本要素协调类使用 描述 建造者模式属于创造型设计模式。 通常用于构建一系列复杂对象&#xff0c;这些对象有一定的共性。 我们可以通过不同的建造者&#xff0c;组装不同的对象 与工厂模式的区别&#xff0c;建造者模式更侧重与基于基础构件组装而非直接创…