GORM入門指南


gorm是一個使用Go語言編寫的ORM框架。它文檔齊全,對開發者友好,支持主流數據庫。

gorm介紹

Github GORM

中文官方網站內含十分齊全的中文文檔,有了它你甚至不需要再繼續向下閱讀本文。

安裝

go get -u github.com/jinzhu/gorm

連接數據庫

連接不同的數據庫都需要導入對應數據的驅動程序,GORM已經貼心的為我們包裝了一些驅動程序,只需要按如下方式導入需要的數據庫驅動即可:

import _ "github.com/jinzhu/gorm/dialects/mysql"
// import _ "github.com/jinzhu/gorm/dialects/postgres"
// import _ "github.com/jinzhu/gorm/dialects/sqlite"
// import _ "github.com/jinzhu/gorm/dialects/mssql"

連接MySQL

import (
  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/mysql"
)

func main() {
  db, err := gorm.Open("mysql", "user:password@(localhost)/dbname?charset=utf8mb4&parseTime=True&loc=Local")
  defer db.Close()
}

連接PostgreSQL

基本代碼同上,注意引入對應postgres驅動並正確指定gorm.Open()參數。

import (
  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/postgres"
)

func main() {
  db, err := gorm.Open("postgres", "host=myhost port=myport user=gorm dbname=gorm password=mypassword")
  defer db.Close()
}

連接Sqlite3

基本代碼同上,注意引入對應sqlite驅動並正確指定gorm.Open()參數。

import (
  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/sqlite"
)

func main() {
  db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
  defer db.Close()
}

連接SQL Server

基本代碼同上,注意引入對應mssql驅動並正確指定gorm.Open()參數。

import (
  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/mssql"
)

func main() {
  db, err := gorm.Open("mssql", "sqlserver://username:password@localhost:1433?database=dbname")
  defer db.Close()
}

GORM基本示例

注意:

  1. 本文以MySQL數據庫為例,講解GORM各項功能的主要使用方法。
  2. 往下閱讀本文前,你需要有一個能夠成功連接上的MySQL數據庫實例。

Docker快速創建MySQL實例

很多同學如果不會安裝MySQL或者懶得安裝MySQL,可以使用一下命令快速運行一個MySQL8.0.19實例,當然前提是你要有docker環境…

在本地的13306端口運行一個名為mysql8019,root用戶名密碼為root1234的MySQL容器環境:

docker run --name mysql8019 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=root1234 -d mysql:8.0.19

在另外啟動一個MySQL Client連接上面的MySQL環境,密碼為上一步指定的密碼root1234:

docker run -it --network host --rm mysql mysql -h127.0.0.1 -P13306 --default-character-set=utf8mb4 -uroot -p

創建數據庫

在使用GORM前手動創建數據庫db1

CREATE DATABASE db1;

GORM操作MySQL

使用GORM連接上面的db1進行創建、查詢、更新、刪除操作。

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// UserInfo 用戶信息
type UserInfo struct {
    ID uint
    Name string
    Gender string
    Hobby string
}


func main() {
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err!= nil{
        panic(err)
    }
    defer db.Close()

    // 自動遷移
    db.AutoMigrate(&UserInfo{})

    u1 := UserInfo{1, "七米", "", "籃球"}
    u2 := UserInfo{2, "沙河娜扎", "", "足球"}
    // 創建記錄
    db.Create(&u1)
    db.Create(&u2)
    // 查詢
    var u = new(UserInfo)
    db.First(u)
    fmt.Printf("%#v\n", u)

    var uu UserInfo
    db.Find(&uu, "hobby=?", "足球")
    fmt.Printf("%#v\n", uu)

    // 更新
    db.Model(&u).Update("hobby", "雙色球")
    // 刪除
    db.Delete(&u)
}

GORM Model定義

在使用ORM工具時,通常我們需要在代碼中定義模型(Models)與數據庫中的數據表進行映射,在GORM中模型(Models)通常是正常定義的結構體、基本的go類型或它們的指針。 同時也支持sql.Scannerdriver.Valuer接口(interfaces)。

gorm.Model

為了方便模型定義,GORM內置了一個gorm.Model結構體。gorm.Model是一個包含了IDCreatedAtUpdatedAtDeletedAt四個字段的Golang結構體。

// gorm.Model 定義
type Model struct {
  ID        uint `gorm:"primary_key"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt *time.Time
}

你可以將它嵌入到你自己的模型中:

// 將 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`字段注入到`User`模型中
type User struct {
  gorm.Model
  Name string
}

當然你也可以完全自己定義模型:

// 不使用gorm.Model,自行定義模型
type User struct {
  ID   int
  Name string
}

模型定義示例

type User struct {
  gorm.Model
  Name         string
  Age          sql.NullInt64
  Birthday     *time.Time
  Email        string  `gorm:"type:varchar(100);unique_index"`
  Role         string  `gorm:"size:255"` // 設置字段大小為255
  MemberNumber *string `gorm:"unique;not null"` // 設置會員號(member number)唯一並且不為空
  Num          int     `gorm:"AUTO_INCREMENT"` // 設置 num 為自增類型
  Address      string  `gorm:"index:addr"` // 給address字段創建名為addr的索引
  IgnoreMe     int     `gorm:"-"` // 忽略本字段
}

結構體標記(tags)

使用結構體聲明模型時,標記(tags)是可選項。gorm支持以下標記:

支持的結構體標記(Struct tags)

結構體標記(Tag) 描述
Column 指定列名
Type 指定列數據類型
Size 指定列大小, 默認值255
PRIMARY_KEY 將列指定為主鍵
UNIQUE 將列指定為唯一
DEFAULT 指定列默認值
PRECISION 指定列精度
NOT NULL 將列指定為非 NULL
AUTO_INCREMENT 指定列是否為自增類型
INDEX 創建具有或不帶名稱的索引, 如果多個索引同名則創建復合索引
UNIQUE_INDEX 和 INDEX 類似,只不過創建的是唯一索引
EMBEDDED 將結構設置為嵌入
EMBEDDED_PREFIX 設置嵌入結構的前綴
- 忽略此字段

關聯相關標記(tags)

結構體標記(Tag) 描述
MANY2MANY 指定連接表
FOREIGNKEY 設置外鍵
ASSOCIATION_FOREIGNKEY 設置關聯外鍵
POLYMORPHIC 指定多態類型
POLYMORPHIC_VALUE 指定多態值
JOINTABLE_FOREIGNKEY 指定連接表的外鍵
ASSOCIATION_JOINTABLE_FOREIGNKEY 指定連接表的關聯外鍵
SAVE_ASSOCIATIONS 是否自動完成 save 的相關操作
ASSOCIATION_AUTOUPDATE 是否自動完成 update 的相關操作
ASSOCIATION_AUTOCREATE 是否自動完成 create 的相關操作
ASSOCIATION_SAVE_REFERENCE 是否自動完成引用的 save 的相關操作
PRELOAD 是否自動完成預加載的相關操作

主鍵、表名、列名的約定

主鍵(Primary Key)

GORM 默認會使用名為ID的字段作為表的主鍵。

type User struct {
  ID   string // 名為`ID`的字段會默認作為表的主鍵
  Name string
}

// 使用`AnimalID`作為主鍵
type Animal struct {
  AnimalID int64 `gorm:"primary_key"`
  Name     string
  Age      int64
}

表名(Table Name)

表名默認就是結構體名稱的復數,例如:

type User struct {} // 默認表名是 `users`

// 將 User 的表名設置為 `profiles`
func (User) TableName() string {
  return "profiles"
}

func (u User) TableName() string {
  if u.Role == "admin" {
    return "admin_users"
  } else {
    return "users"
  }
}

// 禁用默認表名的復數形式,如果置為 true,則 `User` 的默認表名是 `user`
db.SingularTable(true)

也可以通過Table()指定表名:

// 使用User結構體創建名為`deleted_users`的表
db.Table("deleted_users").CreateTable(&User{})

var deleted_users []User
db.Table("deleted_users").Find(&deleted_users)
//// SELECT * FROM deleted_users;

db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
//// DELETE FROM deleted_users WHERE name = 'jinzhu';

GORM還支持更改默認表名稱規則:

gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string  {
  return "prefix_" + defaultTableName;
}

列名(Column Name)

列名由字段名稱進行下划線分割來生成

type User struct {
  ID        uint      // column name is `id`
  Name      string    // column name is `name`
  Birthday  time.Time // column name is `birthday`
  CreatedAt time.Time // column name is `created_at`
}

可以使用結構體tag指定列名:

type Animal struct {
  AnimalId    int64     `gorm:"column:beast_id"`         // set column name to `beast_id`
  Birthday    time.Time `gorm:"column:day_of_the_beast"` // set column name to `day_of_the_beast`
  Age         int64     `gorm:"column:age_of_the_beast"` // set column name to `age_of_the_beast`
}

時間戳跟蹤

CreatedAt

如果模型有 CreatedAt字段,該字段的值將會是初次創建記錄的時間。

db.Create(&user) // `CreatedAt`將會是當前時間

// 可以使用`Update`方法來改變`CreateAt`的值
db.Model(&user).Update("CreatedAt", time.Now())

UpdatedAt

如果模型有UpdatedAt字段,該字段的值將會是每次更新記錄的時間。

db.Save(&user) // `UpdatedAt`將會是當前時間

db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`將會是當前時間

DeletedAt

如果模型有DeletedAt字段,調用Delete刪除該記錄時,將會設置DeletedAt字段為當前時間,而不是直接將記錄從數據庫中刪除。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM