I am using Gorm ORM for my current application. I have one model correspondents to many tables with identical table structures(i.e. column name and type). So my requirement how can I change the table name dynamically while doing the query.
For e.g.
I have product model like Product.go
type Product struct{
ID int
Name strig
Quantity int
}
And we have different products like shirts, jeans and so on and we have same tables like shirts, jeans.
Now I wanted to query the product as per name of the product how can we do that also want to have table created through migrations. But there is only One model than how can we run use Automigrate feature with Gorm.
Updated for GORM v2
DEPRECATED: TableName
will not allow dynamic table name anymore, its result will be cached for future uses.
There is a much easier way to create several tables using the same struct:
// 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)
But, now on the second thought, I would suggest using the embedded struct so that you won't have to call Table
in every query and you can also have additional fields per model while still sharing the same table structure.
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)
Old answer for GORM v1
You're almost there by using table
field inside the struct:
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)
Unfortunately, that does not work with db.Find()
when you need to query for multiple records... The workaround is to specify your table before doing the query
prods := []*Product{}
db.Table("jeans").Where("quantity > 0").Find(&prods)