playground
https://github.com/go-gorm/playground/pull/704
problem
When a Model method is called multiple times, only the first call queries the table, and subsequent calls to the Model method do not update the query table.
Probably not many people use it that way. The reason we use query criteria to query multiple tables is that, in some cases, we set the same fields in multiple tables by embedding struct, which also makes the same query criteria available in all tables. We do this to reduce duplication of logic and simplify the code.
Comment From: github-actions[bot]
The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout https://github.com/go-gorm/playground for details. it will be closed in 30 days if no further activity occurs. if you are asking question, please use the Question template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ Search Before Asking ✨
Comment From: ZiRunHua
It seems that no one else has encountered this problem, but I think this problem needs to be fixed, because the Model method is closely related to the factory method, such as the factory method actually used by the following business:
// ForeignKeyCondition 交易外键查询条件 用于交易记录和统计的查询
type ForeignKeyCondition struct {
AccountId uint
UserIds *[]uint
CategoryIds *[]uint
}
func (f *ForeignKeyCondition) addConditionToQuery(db *gorm.DB) *gorm.DB {
query := db.Where("account_id = ?", f.AccountId)
if f.UserIds != nil {
query = query.Where("user_id IN (?)", *f.UserIds)
}
if f.CategoryIds != nil {
query = query.Where("category_id IN (?)", *f.CategoryIds)
}
return query
}
type statisticModel interface {
GetUpdatesValue(amount, count int) map[string]interface{}
GetDate(tradeTime time.Time) time.Time
}
func (f *ForeignKeyCondition) GetStatistic(ie constant.IncomeExpense) statisticModel {
if ie == constant.Income {
return f.getIncomeStatisticModel()
} else {
return f.getExpendStatisticModel()
}
}
func (f *ForeignKeyCondition) getIncomeStatisticModel() statisticModel {
if f.CategoryIds == nil {
if f.UserIds == nil {
return &IncomeAccountStatistic{}
} else {
return &IncomeAccountUserStatistic{}
}
} else if f.UserIds == nil {
return &IncomeCategoryStatistic{}
}
return nil
}
func (f *ForeignKeyCondition) getExpendStatisticModel() statisticModel {
if f.CategoryIds == nil {
if f.UserIds == nil {
return &ExpenseAccountStatistic{}
} else {
return &ExpenseAccountUserStatistic{}
}
} else if f.UserIds == nil {
return &ExpenseCategoryStatistic{}
}
return nil
}
Although income has many other attributes such as tax, income and expenditure have many same foreign keys, and income and expenditure statistics under the same conditions need to be performed in many scenarios, so we often have the following queries:
type Statistic struct {
Income struct{ Amount, Count int64 }
Expense struct{ Amount, Count int64 }
}
type Dao struct{ db *gorm.DB }
func (d *Dao) SelectIEStatisticByCondition(condition ForeignKeyCondition) (result Statistic, err error) {
query := condition.addConditionToQuery(d.db)
err = query.Model(condition.getIncomeStatisticModel()).Select("SUM(amount) as amount,SUM(count) as count").Scan(&result.Income).Error
if err != nil {
return
}
err = query.Model(condition.getExpendStatisticModel()).Select("SUM(amount) as amount,SUM(count) as count").Scan(&result.Expense).Error
return
}
Having interface statisticModel implement a TableName() string method that is only used by gorm, and then setting the table through Table(condition.getIncomeStatisticModel().TableName()), feels too cumbersome and not beautiful, although we are using it now.