转载

golang gorm关联详解

温馨提示:
本文最后更新于 2022年09月14日,已超过 583 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

最近学习了一下golang一直对于gorm的关联有所疑惑,找到一篇不错的博客。链接如下。
原文链接:https://www.jianshu.com/p/fcef8b425ce9

先看数据结构:
关系图

demo代码如下:

package main

import (
    "fmt"
    "time"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
    ID                uint       `gorm:"primary_key"`
    Birthday          string     `gorm:"column:birthday"`
    Age               int        `gorm:"column:age"`
    Name              string     `gorm:"column:name"`
    BillingAddress    Address    `gorm:"foreignkey:BillingAddressId;"` // One-To-One (属于 - 本表的BillingAddressID作外键
    BillingAddressId  int        `gorm:"column:billing_address_id"`
    ShippingAddress   Address    `gorm:"foreignkey:ShippingAddressId;"` // One-To-One (属于 - 本表的ShippingAddressID作外键)
    ShippingAddressId int        `gorm:"column:shipping_address_id"`
    CreditCard        CreditCard `gorm:"foreignkey:UserID;"`        // One-To-One (拥有一个 - CreditCard表的UserID作外键)
    Emails            []Email    `gorm:"ForeignKey:UserID;"`        // One-To-Many (拥有多个 - Email表的UserID作外键)
    Languages         []Language `gorm:"many2many:user_languages;"` // Many-To-Many , 'user_languages'是连接表
}

type Email struct {
    ID     int    `gorm:"primary_key"`
    UserID int    `gorm:"column:user_id;"` // 外键 (属于), tag `index`是为该列创建索引
    Email  string `gorm:"column:email"`    // `type`设置sql类型, `unique_index` 为该列设置唯一索引
}

type Address struct {
    ID       int    `gorm:"primary_key"`
    Address1 string `gorm:"column:address1"` // 设置字段为非空并唯一
    Address2 string `gorm:"column:address2"`
    Post     string `gorm:"column:post"`
}

type Language struct {
    ID   int    `gorm:"primary_key"`
    Name string `gorm:"column:name"` // 创建索引并命名,如果找到其他相同名称的索引则创建组合索引
    Code string `gorm:"column:code"` // `unique_index` also works
}

type CreditCard struct {
    ID     int    `gorm:"primary_key"`
    UserID int    `gorm:"column:user_id;"`
    Number string `gorm:"column:number"`
}

func main() {
    url := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8&parseTime=True&loc=Local", "root", "xxxxx", "localhost:3306", "demo")
    db, err := gorm.Open("mysql", url)
    db.AutoMigrate(
        &User{},
        &Email{},
        &Address{},
        &Language{},
        &CreditCard{},
    )
    db.LogMode(true)
    if err != nil {
        panic("failed to connect database")
    }
    db.DB().SetMaxIdleConns(30)
    db.DB().SetMaxOpenConns(60)
    defer db.Close()
    defer func() {
        if e := recover(); e != nil {
            fmt.Println(e)
        }
    }()
    t1 := time.Now()
    u := User{ID: 1}
    db.Model(&u).Find(&u)
    db.Model(&u).Related(&u.CreditCard, "CreditCard")
    db.Model(&u).Related(&u.Emails, "Emails")
    db.Model(&u).Related(&u.Languages, "Languages")
    db.Model(&u).Related(&u.BillingAddress, "BillingAddress")
    db.Model(&u).Related(&u.ShippingAddress, "ShippingAddress")
    fmt.Println(u)
    t2 := time.Now()
    fmt.Println("gorm耗时:", t2.Sub(t1))
}

func (u User) TableName() string {
    return "user"
}

func (u Email) TableName() string {
    return "email"
}

func (u Address) TableName() string {
    return "address"
}

func (u Language) TableName() string {
    return "language"
}

func (u CreditCard) TableName() string {
    return "creditcard"
}

运行结果

{1 1999-10-01 20 张三 {2 武汉市汉阳区 武汉市关山大道 4300000} 2 {1 武汉市洪山区 武汉市关山大道 4300000} 1 {11 1 xxxx-11111} [{1 1 11@11.com} {2 1 22@11.com}] [{1 汉语 ch} {2 英语 en}]}

总结:
belongs_to,has_one主要是用于1对1的关系.has_many用于1对多关系,many_to_many用于多对多.
感觉gorm最大的优势就是能级联查询,但是就是例子太少,官方文档也太简略.

正文到此结束