如何在 gorm 模型中传递动态 table 名称
How to pass dynamic table name in gorm model
我正在为我当前的应用程序使用 Gorm ORM。我有一个模型对应许多具有相同 table 结构(即列名和类型)的 table。所以我的要求是如何在查询时动态更改 table 名称。
例如
我有像Product.go
这样的产品型号
type Product struct{
ID int
Name strig
Quantity int
}
我们有不同的产品,如衬衫、牛仔裤等,我们有相同的 table 产品,如衬衫、牛仔裤。
现在我想根据产品名称查询产品,我们该怎么做,还想通过迁移创建 table。但是只有一个模型,我们如何才能 运行 使用 Gorm 的自动迁移功能。
已更新 GORM v2
已弃用:TableName
将不再允许动态 table 名称,其结果将被缓存以备将来使用。
有一种更简单的方法可以使用相同的结构创建多个 table:
// Create table `shirts` & `jeans` with the same fields as in struct Product
db.Table("shirts").AutoMigrate(&Product{})
db.Table("jeans").AutoMigrate(&Product{})
// Query data from those tables
var shirts []Product
var jeans []Product
db.Table("shirts").Find(&shirts)
db.Table("jeans").Where("quantity > 0").Find(&shirts)
但是,现在再想一想,我建议使用嵌入式结构,这样您就不必在每个查询中调用 Table
,并且您还可以在每个模型中拥有额外的字段,同时仍然共享相同的 table 结构。
type ProductBase struct {
ID int
Name strig
Quantity int
}
type Shirt struct {
ProductBase
NeckType string
}
type Jean struct {
ProductBase
Ripped bool
}
db.AutoMigrate(&Shirt{}, &Jean{})
shirt, jeans := Shirt{}, make([]Jean, 0)
db.Where("neck_type = ?", "Mandarin Collar").Last(&shirt)
db.Where("ripped").Find(&jeans)
GORM v1 的旧答案
通过在结构中使用 table
字段,您就快完成了:
type Product struct{
ID int
Name strig
Quantity int
// private field, ignored from gorm
table string `gorm:"-"`
}
func (p Product) TableName() string {
// double check here, make sure the table does exist!!
if p.table != "" {
return p.table
}
return "products" // default table name
}
// for the AutoMigrate
db.AutoMigrate(&Product{table: "jeans"}, &Product{table: "skirts"}, &Product{})
// to do the query
prod := Product{table: "jeans"}
db.Where("quantity > 0").First(&prod)
不幸的是,当您需要查询多条记录时,这不适用于 db.Find()
...解决方法是在执行查询之前指定您的 table
prods := []*Product{}
db.Table("jeans").Where("quantity > 0").Find(&prods)
我正在为我当前的应用程序使用 Gorm ORM。我有一个模型对应许多具有相同 table 结构(即列名和类型)的 table。所以我的要求是如何在查询时动态更改 table 名称。
例如
我有像Product.go
这样的产品型号type Product struct{
ID int
Name strig
Quantity int
}
我们有不同的产品,如衬衫、牛仔裤等,我们有相同的 table 产品,如衬衫、牛仔裤。
现在我想根据产品名称查询产品,我们该怎么做,还想通过迁移创建 table。但是只有一个模型,我们如何才能 运行 使用 Gorm 的自动迁移功能。
已更新 GORM v2
已弃用:TableName
将不再允许动态 table 名称,其结果将被缓存以备将来使用。
有一种更简单的方法可以使用相同的结构创建多个 table:
// Create table `shirts` & `jeans` with the same fields as in struct Product
db.Table("shirts").AutoMigrate(&Product{})
db.Table("jeans").AutoMigrate(&Product{})
// Query data from those tables
var shirts []Product
var jeans []Product
db.Table("shirts").Find(&shirts)
db.Table("jeans").Where("quantity > 0").Find(&shirts)
但是,现在再想一想,我建议使用嵌入式结构,这样您就不必在每个查询中调用 Table
,并且您还可以在每个模型中拥有额外的字段,同时仍然共享相同的 table 结构。
type ProductBase struct {
ID int
Name strig
Quantity int
}
type Shirt struct {
ProductBase
NeckType string
}
type Jean struct {
ProductBase
Ripped bool
}
db.AutoMigrate(&Shirt{}, &Jean{})
shirt, jeans := Shirt{}, make([]Jean, 0)
db.Where("neck_type = ?", "Mandarin Collar").Last(&shirt)
db.Where("ripped").Find(&jeans)
GORM v1 的旧答案
通过在结构中使用 table
字段,您就快完成了:
type Product struct{
ID int
Name strig
Quantity int
// private field, ignored from gorm
table string `gorm:"-"`
}
func (p Product) TableName() string {
// double check here, make sure the table does exist!!
if p.table != "" {
return p.table
}
return "products" // default table name
}
// for the AutoMigrate
db.AutoMigrate(&Product{table: "jeans"}, &Product{table: "skirts"}, &Product{})
// to do the query
prod := Product{table: "jeans"}
db.Where("quantity > 0").First(&prod)
不幸的是,当您需要查询多条记录时,这不适用于 db.Find()
...解决方法是在执行查询之前指定您的 table
prods := []*Product{}
db.Table("jeans").Where("quantity > 0").Find(&prods)