beego报错 table name: `xxx` not exists
一、问题
在学习beego中出现了Handler crashed with error <Ormer.QueryTable> table name: 'users' not exists
的报错。
示例代码:
models:
func init() {
orm.RegisterModel(new(User))
}
type User struct {
Id int64
Name string
}
controllers:
func (u *UserController) Index() {
var users []models.User
orm.NewOrm().QueryTable("users").All(&users)
fmt.Println(users)
}
二、查找问题
- 首先找到beego报错的地方,在
beego/client/orm/orm.go
文件中QueryTableWithCtx方法。
func (o *ormBase) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) (qs QuerySeter) {
var name string
if table, ok := ptrStructOrTableName.(string); ok {
name = nameStrategyMap[defaultNameStrategy](table)
if mi, ok := modelCache.get(name); ok {
qs = newQuerySet(o, mi)
}
} else {
name = getFullName(indirectType(reflect.TypeOf(ptrStructOrTableName)))
if mi, ok := modelCache.getByFullName(name); ok {
qs = newQuerySet(o, mi)
}
}
if qs == nil {
panic(fmt.Errorf("<Ormer.QueryTable> table name: `%s` not exists", name))
}
return
}
ptrStructOrTableName
参数是表名(string
类型),由此判断是在modelCache.get(name)
出错,进入其方法:
// get model info by table name
func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) {
mi, ok = mc.cache[table]
return
}
进一步判断,传入的表名不存在_modelCache
,而在在QueryTable
之前仅有orm.RegisterModel(new(User))
是注册model
方法。
- 追查
orm.RegisterModel
方法最终调用的是在beego/client/orm/models.go
中的register方法:
// register register models to model cache
func (mc *_modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, models ...interface{}) (err error) {
... // 省略代码
for _, model := range models {
...
table := getTableName(val)
if prefixOrSuffixStr != "" {
if prefixOrSuffix {
table = prefixOrSuffixStr + table
} else {
table = table + prefixOrSuffixStr
}
}
...
mi.table = table
mi.pkg = typ.PkgPath()
mi.model = model
mi.manual = true
mc.set(table, mi)
}
return
}
register
方法会先通过getTableName
查询是否实现TableName
方法,如果实现会直接获取TableName
返回的表名,然后判断是否增加前缀或者后缀。
// getTableName get struct table name.
// If the struct implement the TableName, then get the result as tablename
// else use the struct name which will apply snakeString.
func getTableName(val reflect.Value) string {
if fun := val.MethodByName("TableName"); fun.IsValid() { // 判断是否实现TableName方法fun.IsValid()
vals := fun.Call([]reflect.Value{})
// has return and the first val is string
if len(vals) > 0 && vals[0].Kind() == reflect.String {
return vals[0].String()
}
}
return snakeString(reflect.Indirect(val).Type().Name())
}
三、解决方法
通过代码的追踪,发现报错的原因是QueryTable(”users“)
传入的参数与注册的User Model
并不匹配,根据源码解决办法有三种:
修改传入参数
users
改为user
,并更改数据库中的表名orm.NewOrm().QueryTable("user").All(&users)
在
User Model
中实现TableName
方法func (u *User) TableName() string { return "users" }
注册model时使用后缀
orm.RegisterModelWithSuffix("s", new(User))
四、总结
1、beego中QueryTable
方法中表名参数是与注册Model
相关联的。
2、如果数据库中表名和Model
名称不相同时,可使用实现TableName
方法或者注册model
时添加前缀RegisterModelWithPrefix
、添加后缀RegisterModelWithSuffix
时注册实际表名。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: