简体   繁体   中英

How to pass dynamic table name in gorm model

I am using Gorm ORM for my current application. I have one model correspondents to many tables with identical table structures(ie column name and type). So my requirement how can I change the table name dynamically while doing the query.

For eg

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM