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 协议》,转载必须注明作者和本文链接
关于 LearnKu
推荐文章: