【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.pswp.cn/bicheng/75907.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75907.shtml
英文地址,請注明出處:http://en.pswp.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;建造者模式更側重與基于基礎構件組裝而非直接創…