golang

gorm关联详解

2019-02-19  本文已影响17人  林子老公

学习gorm时,感觉文档中的related相关内容比较模糊,没有一个完整的实例.看了源码之后,才把整个原理搞清楚.

先看数据结构:

gorm-related.png

demo代码如下:

package main

import (
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
    "time"
)

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", "123456", "localhost:3306", "demo")
    db, err := gorm.Open("mysql", url)
    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最大的优势就是能级联查询,但是就是例子太少,官方文档也太简略.

上一篇下一篇

猜你喜欢

热点阅读