在Gorm(Go语言的ORM库)中使用指针引用来关联外键模型。

huangapple go评论85阅读模式
英文:

Using a pointer reference to a foreign-key related model in Gorm (golang)

问题

假设你有以下数据库模型:

package storage

type Country struct {
	ID   string `json:"id" gorm:"type:uuid"`
	Name string `json:"name"`
	Code string `json:"code"`
}

type City struct {
	ID           string   `json:"id" gorm:"type:uuid"`
	Name         string   `json:"name"`
	Code         *string  `json:"code"`
	CountryId    string   `json:"country_id"`
	Country      *Country `json:"country" gorm:"references:ID"`
	IATA         *string  `json:"iata"`
	Latitude     *string  `json:"latitude"`
	Longitude    *string  `json:"longitude"`
}

为了更容易理解是否已经连接了 Country(在 SQL 中)或者没有连接(例如 if city.Country == nil {panic("for whatever reason")}),城市应该有一个指向 Country 模型的指针。

当我尝试获取所有城市的列表时出现了问题:

package example

var cities []storage.City 
tx.Joins("Country").Find(&cities)

在这里,所有的城市都已经从数据库中获取到了,但是所有的城市的国家都变成了相同的

期望的输出
[
{
 ID:51e415ab-4301-4268-9345-deed6b1d72f6 
 Name:Bergen 
 Code:0xc0004d6ec0 
 CountryId:0bd3890c-b6b7-4b27-8071-55c8f64562bb 
 Country:{
    ID:0bd3890c-b6b7-4b27-8071-55c8f64562bb 
    Name:Norwegen 
    Code:NO
   } 
 SkyScannerId:0xc0004d6ee0 
 IATA:0xc0004d6ef0 
 Latitude:0xc0004d6f00 
 Longitude:0xc0004d6f10
},
 
{
 ID:2468c7f0-0275-4bff-8b7e-4e87bfa63604 
 Name:Banská Bystrica 
 Code:0xc0004d6bc0 
 CountryId:00ba76d3-9591-4d45-a39d-f554375d790f 
 Country: {
    ID:00ba76d3-9591-4d45-a39d-f554375d790f 
    Name:Slovakei 
    Code:SK
   } 
 SkyScannerId:<nil> 
 IATA:<nil> 
 Latitude:0xc0004d6c00 
 Longitude:0xc0004d6c10
}, 

{
 ID:75501988-3c80-4ef9-8081-73d20cbcc29b 
 Name:Prag 
 Code:0xc0004d6a60 
 CountryId:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e 
 Country:{
    ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e 
    Name:Tschechien 
    Code:CZ
  } 
 SkyScannerId:0xc0004d6a90 
 IATA:0xc0004d6aa0 
 Latitude:0xc0004d6ac0 
 Longitude:0xc0004d6ad0
}
] 

实际的输出

[
{
 ID:51e415ab-4301-4268-9345-deed6b1d72f6 
 Name:Bergen 
 Code:0xc0004d6ec0 
 CountryId:0bd3890c-b6b7-4b27-8071-55c8f64562bb 
 Country:{
    ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e 
    Name:Tschechien 
    Code:CZ
  }
 SkyScannerId:0xc0004d6ee0 
 IATA:0xc0004d6ef0 
 Latitude:0xc0004d6f00 
 Longitude:0xc0004d6f10
},
 
{
 ID:2468c7f0-0275-4bff-8b7e-4e87bfa63604 
 Name:Banská Bystrica 
 Code:0xc0004d6bc0 
 CountryId:00ba76d3-9591-4d45-a39d-f554375d790f 
 Country:{
    ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e 
    Name:Tschechien 
    Code:CZ
  }
 SkyScannerId:<nil> 
 IATA:<nil> 
 Latitude:0xc0004d6c00 
 Longitude:0xc0004d6c10
}, 

{
 ID:75501988-3c80-4ef9-8081-73d20cbcc29b 
 Name:Prag 
 Code:0xc0004d6a60 
 CountryId:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e 
 Country:{
    ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e 
    Name:Tschechien 
    Code:CZ
  } 
 SkyScannerId:0xc0004d6a90 
 IATA:0xc0004d6aa0 
 Latitude:0xc0004d6ac0 
 Longitude:0xc0004d6ad0
}
] 

请注意**输出中的 Country 字段**在实际输出中所有的城市都有相同的国家我认为这与指针有关
当我从 Country **移除指针**所以 `*Country` 变成了没有 `*`  `Country`我得到了期望的输出但是我想要在指针`*Country`的情况下得到相同的输出
另外请不要关注其他字段中打印出的值我的主要关注点是 Country 字段

有什么办法可以修复这个问题吗

P.S. 我知道我也可以在 Country 字段中不使用指针但我只是想知道是否有任何可能性可以这样做

<details>
<summary>英文:</summary>

Suppose you have database models as follows:

package storage

type Country struct {
ID string json:&quot;id&quot; gorm:&quot;type:uuid&quot;
Name string json:&quot;name&quot;
Code string json:&quot;code&quot;
}

type City struct {
ID string json:&quot;id&quot; gorm:&quot;type:uuid&quot;
Name string json:&quot;name&quot;
Code *string json:&quot;code&quot;
CountryId string json:&quot;country_id&quot;
Country *Country json:&quot;country&quot; gorm:&quot;references:ID&quot;
IATA *string json:&quot;iata&quot;
Latitude *string json:&quot;latitude&quot;
Longitude *string json:&quot;longitude&quot;
}


The city should have a pointer to a Country model to make it easier to understand whether Country has been joined (in sql) or not (e.g. ```if city.Country == nil {panic(&quot;for whatever reason&quot;)}``` )
**The problem appears when I try to get the list of all cities:**

package example

var cities []storage.City
tx.Joins("Country").Find(&cities)


Here, all the cities have been fetched from DB nicely, but the **countries became the same in all the cities.**

EXPECTED OUTPUT
[
{
ID:51e415ab-4301-4268-9345-deed6b1d72f6
Name:Bergen
Code:0xc0004d6ec0
CountryId:0bd3890c-b6b7-4b27-8071-55c8f64562bb
Country:{
ID:0bd3890c-b6b7-4b27-8071-55c8f64562bb
Name:Norwegen
Code:NO
}
SkyScannerId:0xc0004d6ee0
IATA:0xc0004d6ef0
Latitude:0xc0004d6f00
Longitude:0xc0004d6f10
},

{
ID:2468c7f0-0275-4bff-8b7e-4e87bfa63604
Name:Banská Bystrica
Code:0xc0004d6bc0
CountryId:00ba76d3-9591-4d45-a39d-f554375d790f
Country: {
ID:00ba76d3-9591-4d45-a39d-f554375d790f
Name:Slovakei
Code:SK
}
SkyScannerId:<nil>
IATA:<nil>
Latitude:0xc0004d6c00
Longitude:0xc0004d6c10
},

{
ID:75501988-3c80-4ef9-8081-73d20cbcc29b
Name:Prag
Code:0xc0004d6a60
CountryId:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e
Country:{
ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e
Name:Tschechien
Code:CZ
}
SkyScannerId:0xc0004d6a90
IATA:0xc0004d6aa0
Latitude:0xc0004d6ac0
Longitude:0xc0004d6ad0
}
]

ACTUAL OUTPUT:

[
{
ID:51e415ab-4301-4268-9345-deed6b1d72f6
Name:Bergen
Code:0xc0004d6ec0
CountryId:0bd3890c-b6b7-4b27-8071-55c8f64562bb
Country:{
ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e
Name:Tschechien
Code:CZ
}
SkyScannerId:0xc0004d6ee0
IATA:0xc0004d6ef0
Latitude:0xc0004d6f00
Longitude:0xc0004d6f10
},

{
ID:2468c7f0-0275-4bff-8b7e-4e87bfa63604
Name:Banská Bystrica
Code:0xc0004d6bc0
CountryId:00ba76d3-9591-4d45-a39d-f554375d790f
Country:{
ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e
Name:Tschechien
Code:CZ
}
SkyScannerId:<nil>
IATA:<nil>
Latitude:0xc0004d6c00
Longitude:0xc0004d6c10
},

{
ID:75501988-3c80-4ef9-8081-73d20cbcc29b
Name:Prag
Code:0xc0004d6a60
CountryId:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e
Country:{
ID:f4e819b2-5c1a-43f9-bfa1-fe56b6ee173e
Name:Tschechien
Code:CZ
}
SkyScannerId:0xc0004d6a90
IATA:0xc0004d6aa0
Latitude:0xc0004d6ac0
Longitude:0xc0004d6ad0
}
]


Please pay attention to **Country field of the outputs**. In the ACTUAL OUTPUT all the cities have the same country. I think this has something to do with the pointer. 
I **got** EXPECTED OUTPUT when I **removed** **the** **pointer** from Country (so ```*Country``` became ```Country``` without ```*```). But I would like to get the same output with the pointer (```*Country```).
Also, please do not pay attention to the values printed out in other fields. My main focus is the Country field.
Any ideas how to fix it ? 
P.S. I know that i can survive without using the pointers too in the Country field, but I just want to know if there are any possibilities to do that.
</details>
# 答案1
**得分**: 1
尝试将countryId也作为指针传递。
像这样:
CountryId    *string   `json:"country_id"`
实际上,我尝试使用你的代码示例复制错误,但它运行良好。
<details>
<summary>英文:</summary>
Try to put countryId as a pointer too. 
Like this
CountryId    *string   `json:&quot;country_id&quot;`
Actually I tried to replicate the error with you code example, but it&#39;s working well. 
</details>
# 答案2
**得分**: 0
我注意到这是 ```gorm-v1.23.6``` 的行为。切换回 ```gorm-v1.23.5``` 解决了这个问题。
<details>
<summary>英文:</summary>
I have noticed that this is the behavior with ```gorm-v1.23.6```.  Switching back to ```gorm-v1.23.5``` solved the problem. 
</details>

huangapple
  • 本文由 发表于 2022年6月12日 03:43:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/72587394.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定