美文网首页
gorm-关联-一对一关联(BelongsTo/HasOne)

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

作者: 玄德公笔记 | 来源:发表于2022-02-13 20:54 被阅读0次

1. 概念

1.1 相同

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

1.2 区别

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

  • BelongsTo
    B模型引用A模型,利用B模型在B表中创建数据,同时也会在A表中创建对应数据。
  • Has One
    A模型引用B模型,在A模型在A表中创建数据,同时也会在B表中创建对应数据。

1. BelongsTo

1.1 创建模型

  • 一张users表,一张spouse表。
  • 创建两个模型(结构体),使得Spouse 属于User
  • 两个模型分别对应两张表:User ----> users,Spouse----> spouses
  • 结构体Spouse 引用了 结构体User
    则默认Spouse.UserID 对应了spouses表的外键user_id
    且引用了User.ID 对应的users表的id键
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 创建数据

  • 代码
    替换 "1.3 完整示例" 中main函数
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}

相关文章

网友评论

      本文标题:gorm-关联-一对一关联(BelongsTo/HasOne)

      本文链接:https://www.haomeiwen.com/subject/jojokrtx.html