GORM 预加载:如何使用自定义 table 名称
GORM preload: How to use a custom table name
我有一个带有预加载的 GORM 查询,它工作得很好,因为我将它绑定到一个名为“companies”的结构,它也是相应数据库的名称table:
var companies []Company
db.Preload("Subsidiaries").Joins("LEFT JOIN company_prod ON company_products.company_id = companies.id").Where("company_products.product_id = ?", ID).Find(&companies)
现在我想做类似的事情,但将结果绑定到一个没有引用“公司”名称的结构 table:
var companiesFull []CompanyFull
db.Preload("Subsidiaries").Joins("LEFT JOIN company_prod ON company_products.company_id = companies.id").Where("company_products.product_id = ?", ID).Find(&companies)
我简化了第二个调用以便更好地理解,真正的调用有更多的 JOIN 和 returns 更多的数据,所以它不能绑定到“companies”结构。
不过我遇到了一个错误:
column company_subsidiaries.company_full_id does not exist
对应SQL查询:
SELECT * FROM "company_subsidiaries" WHERE "company_subsidiaries"."company_full_id" IN (2,1)
没有“company_subsidiaries.company_full_id”,正确的查询应该是:
SELECT * FROM "company_subsidiaries" WHERE "company_subsidiaries"."company_id" IN (2,1)
条件显然是从结果绑定到的结构的名称生成的。有没有办法为这种情况指定自定义名称?
我知道 Tabler interface technique,但我相信它对 Preload 不起作用(试过了,它更改了主查询的 table 名称,但不是预加载) .
更新:关于数据库架构和结构的更多信息
数据库模式
TABLE companies
ID Primary key
OTHER FIELDS
TABLE products
ID Primary key
OTHER FIELDS
TABLE subsidiaries
ID Primary key
OTHER FIELDS
TABLE company_products
ID Primary key
Company_id Foreign key (companies.id)
Product_id Foreign key (products.id)
TABLE company_subsidiaries
ID Primary key
Company_id Foreign key (companies.id)
Subsidiary_id Foreign key (subsidiaries.id)
结构
type Company struct {
Products []*Product `json:"products" gorm:"many2many:company_products;"`
ID int `json:"ID,omitempty"`
}
type CompanyFull struct {
Products []*Product `json:"products" gorm:"many2many:company_products;"`
Subsidiaries []*Subsidiary `json:"subsidiaries" gorm:"many2many:company_products;"`
ID int `json:"ID,omitempty"`
}
type Product struct {
Name string `json:"name"`
ID int `json:"ID,omitempty"`
}
type Subsidiary struct {
Name string `json:"name"`
ID int `json:"ID,omitempty"`
}
生成 SQL(由 GORM)
SELECT * FROM "company_subsidiaries" WHERE "company_subsidiaries"."company_full_id" IN (2,1)
SELECT * FROM "subsidiaries" WHERE "subsidiaries"."id" IN (NULL)
SELECT companies.*, company_products.*, FROM "companies" LEFT JOIN company_products ON company_products.company_id = companies.id WHERE company_products.product_id = 1
似乎在这种情况下要走的路可能是在您的 CompanyFull 模型中自定义关系。使用 joinForeignKey 以下代码有效。
type CompanyFull struct {
Products []*Product `json:"products" gorm:"many2many:company_products;joinForeignKey:ID"`
Subsidiaries []*Subsidiary `json:"subsidiaries" gorm:"many2many:company_subsidiaries;joinForeignKey:ID"`
ID int `json:"ID,omitempty"`
}
func (CompanyFull) TableName() string {
return "companies"
}
func main(){
...
result := db.Preload("Subsidiaries").Joins("LEFT JOIN company_products ON company_products.company_id = companies.id").Where("company_products.product_id = ?", ID).Find(&companies)
if result.Error != nil {
log.Println(result.Error)
} else {
log.Printf("%#v", companies)
}
有关自定义关系中使用的外键的更多信息,请查看文档 https://gorm.io/docs/many_to_many.html#Override-Foreign-Key
我有一个带有预加载的 GORM 查询,它工作得很好,因为我将它绑定到一个名为“companies”的结构,它也是相应数据库的名称table:
var companies []Company
db.Preload("Subsidiaries").Joins("LEFT JOIN company_prod ON company_products.company_id = companies.id").Where("company_products.product_id = ?", ID).Find(&companies)
现在我想做类似的事情,但将结果绑定到一个没有引用“公司”名称的结构 table:
var companiesFull []CompanyFull
db.Preload("Subsidiaries").Joins("LEFT JOIN company_prod ON company_products.company_id = companies.id").Where("company_products.product_id = ?", ID).Find(&companies)
我简化了第二个调用以便更好地理解,真正的调用有更多的 JOIN 和 returns 更多的数据,所以它不能绑定到“companies”结构。
不过我遇到了一个错误:
column company_subsidiaries.company_full_id does not exist
对应SQL查询:
SELECT * FROM "company_subsidiaries" WHERE "company_subsidiaries"."company_full_id" IN (2,1)
没有“company_subsidiaries.company_full_id”,正确的查询应该是:
SELECT * FROM "company_subsidiaries" WHERE "company_subsidiaries"."company_id" IN (2,1)
条件显然是从结果绑定到的结构的名称生成的。有没有办法为这种情况指定自定义名称?
我知道 Tabler interface technique,但我相信它对 Preload 不起作用(试过了,它更改了主查询的 table 名称,但不是预加载) .
更新:关于数据库架构和结构的更多信息
数据库模式
TABLE companies
ID Primary key
OTHER FIELDS
TABLE products
ID Primary key
OTHER FIELDS
TABLE subsidiaries
ID Primary key
OTHER FIELDS
TABLE company_products
ID Primary key
Company_id Foreign key (companies.id)
Product_id Foreign key (products.id)
TABLE company_subsidiaries
ID Primary key
Company_id Foreign key (companies.id)
Subsidiary_id Foreign key (subsidiaries.id)
结构
type Company struct {
Products []*Product `json:"products" gorm:"many2many:company_products;"`
ID int `json:"ID,omitempty"`
}
type CompanyFull struct {
Products []*Product `json:"products" gorm:"many2many:company_products;"`
Subsidiaries []*Subsidiary `json:"subsidiaries" gorm:"many2many:company_products;"`
ID int `json:"ID,omitempty"`
}
type Product struct {
Name string `json:"name"`
ID int `json:"ID,omitempty"`
}
type Subsidiary struct {
Name string `json:"name"`
ID int `json:"ID,omitempty"`
}
生成 SQL(由 GORM)
SELECT * FROM "company_subsidiaries" WHERE "company_subsidiaries"."company_full_id" IN (2,1)
SELECT * FROM "subsidiaries" WHERE "subsidiaries"."id" IN (NULL)
SELECT companies.*, company_products.*, FROM "companies" LEFT JOIN company_products ON company_products.company_id = companies.id WHERE company_products.product_id = 1
似乎在这种情况下要走的路可能是在您的 CompanyFull 模型中自定义关系。使用 joinForeignKey 以下代码有效。
type CompanyFull struct {
Products []*Product `json:"products" gorm:"many2many:company_products;joinForeignKey:ID"`
Subsidiaries []*Subsidiary `json:"subsidiaries" gorm:"many2many:company_subsidiaries;joinForeignKey:ID"`
ID int `json:"ID,omitempty"`
}
func (CompanyFull) TableName() string {
return "companies"
}
func main(){
...
result := db.Preload("Subsidiaries").Joins("LEFT JOIN company_products ON company_products.company_id = companies.id").Where("company_products.product_id = ?", ID).Find(&companies)
if result.Error != nil {
log.Println(result.Error)
} else {
log.Printf("%#v", companies)
}
有关自定义关系中使用的外键的更多信息,请查看文档 https://gorm.io/docs/many_to_many.html#Override-Foreign-Key