gorm-关联-一对一关联(BelongsTo/HasOne)

2022-02-13  本文已影响0人  玄德公笔记

1. 概念

1.1 相同

都是建立模型的一对一连接,使得模型声明每个实例都「属于」另一个模型的一个实例 。

1.2 区别

假设B模型属于A模型,则B表中存在外键,它和A表中指定列关联。

1. BelongsTo

1.1 创建模型

type User struct {
    //gorm.Model
    ID int64
    Name string
    Age int64
}

type Spouse struct {
    //gorm.Model
    Name      string
    User      User
    UserID int64
    Age int64
}

1.2 写入数据

创建结构体p1,将数据一次写入users、spouse两张表

    p1 := &Spouse{
        User: User{
            Name: "LiuBei",
            Age: 28,
        },
        Name: "SunShangXiang",
        Age: 16,
    }

    db.Create(p1)

1.3 完整示例

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {
    //gorm.Model
    ID int64
    Name string
    Age int64
}

type Spouse struct {
    //gorm.Model
    Name      string
    User      User
    UserID int64
    Age int64
}



func main() {

    db,_ := connect()
    defer db.Close()

    p1 := &Spouse{
        User: User{
            Name: "LiuBei",
            Age: 28,
        },
        Name: "SunShangXiang",
        Age: 16,

    }

    //db.Create(p1)
    result := db.Create(p1)
    fmt.Println(result.Value)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}
mysql> select * from users;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | LiuBei |   28 |
+----+--------+------+
1 row in set (0.00 sec)

mysql> select * from spouses;
+----+---------------+------+---------+
| id | name          | age  | user_id |
+----+---------------+------+---------+
|  4 | SunShangXiang |   16 |       1 |
+----+---------------+------+---------+
1 row in set (0.00 sec)

如上可见,同时在两张表里写入了数据,外键spouses.user_id关联了users.id

1.4 用外键查询

利用&User{ID: 1} 查询spouses表中的数据。

func main() {

   db,_ := connect()
   defer db.Close()

   var spouse Spouse
   db.Model(&User{ID: 1}).Related(&spouse)
   fmt.Println(spouse)
}

输出结果

OK
{SunShangXiang {0  0} 1 16}

1.5 自定义外键名

如前所述,默认外键名为 “表名+ 关联外键名",其对应结构体成员为 User+ID 即UserID
如果我们要自定义,则使用foreignkey指定,如下:

type User struct {
    //gorm.Model
    ID int64
    Name string
    Age int64
}

type Spouse struct {
    //gorm.Model
    Name      string
    User      User `gorm:"foreignkey:HusbandID"`
    HusbandID int64
    Age int64
}

1.6 自定义关联外键

关联外键默认使用主键,即users表的id。如果要自定义,则修改如下:

type User struct {
    //gorm.Model
    ID int64
    Name string
    Age int64
}

type Spouse struct {
    //gorm.Model
    Name      string
    User      User `gorm:"association_foreignkey:Name"`
    UserName string
    Age int64
}

2. HasOne

2.1 创建模型

和 BelongsTo几乎相同,都是一对一关联,且Spouse模型属于User模型(即Spouse的外键关联到User指定列)
不同仅是两个模型谁引用谁。但都是谁引用就用谁创建数据。

替换 "1.3 完整示例" 中两个结构体

type User struct {
    //gorm.Model
    ID int64
    Name string
    Age int64
    Spouse Spouse
}

type Spouse struct {
    //gorm.Model
    Name string
    Age int64
    UserID int64
}

2.2 创建数据

func main() {
    db,_ := connect()
    defer db.Close()

    p1 := &User{
        Name: "ZhangFei",
        Age: 22,
        Spouse: Spouse{
            Name: "XiaHouJuan",
            Age: 18,
        },
    }

    result := db.Create(p1)
    fmt.Println(result.Value)
}
OK
&{6 ZhangFei 22 {XiaHouJuan 18 6}}
mysql> select * from users;
+----+----------+------+-----------+
| id | name     | age  | spouse_id |
+----+----------+------+-----------+
|  6 | ZhangFei |   22 |      NULL |
+----+----------+------+-----------+
1 row in set (0.00 sec)

mysql> select * from spouses;
+----+------------+------+---------+
| id | name       | age  | user_id |
+----+------------+------+---------+
|  2 | XiaHouJuan |   18 |       6 |
+----+------------+------+---------+
1 row in set (0.00 sec)

2.3 修改外键

默认外键名 被关联表名+被关联列名,我们可以作出如下修改,使得spouses.user_name关联到users.name

type User struct {
    //gorm.Model
    ID int64
    Name string
    Age int64
    Spouse Spouse `gorm:"foreignkey:user_name;association_foreignkey:name"`
}

type Spouse struct {
    //gorm.Model
    Name string
    Age int64
    UserName string

}
mysql> select * from spouses;
+----+------------+------+-----------+
| id | name       | age  | user_name |
+----+------------+------+-----------+
|  3 | XiaHouJuan |   18 | ZhangFei  |
+----+------------+------+-----------+
1 row in set (0.00 sec)

mysql> select * from users;
+----+----------+------+
| id | name     | age  |
+----+----------+------+
|  7 | ZhangFei |   22 |
+----+----------+------+
1 row in set (0.00 sec)

2.4 使用外键查询

db.Model(&User{ID: 10}).Related(&spouse,"user_id")

通过User.ID的值,查spouse表的内容

mysql> mysql> select users;
+----+----------+------+
| id | name     | age  |
+----+----------+------+
| 10 | ZhangFei |   22 |
+----+----------+------+
1 row in set (0.00 sec)

mysql> select * from spouses;
+----+------------+------+-----------+---------+
| id | name       | age  | user_name | user_id |
+----+------------+------+-----------+---------+
|  4 | XiaHouJuan |   18 | NULL      |      10 |
+----+------------+------+-----------+---------+
1 row in set (0.00 sec)

代码

func main() {
    db,_ := connect()
    defer db.Close()

    var spouse Spouse
    db.Model(&User{ID: 10}).Related(&spouse,"user_id")
    fmt.Println(spouse)
}

查询结果

OK
{XiaHouJuan 18 10}
上一篇 下一篇

猜你喜欢

热点阅读