专注于
IT技术和业内交流

Beego的QueryTable

今天在调orm的QueryTable时遇到错误:

<Ormer.QueryTable> table name: `system_nickname` not exists

查看QueryTable的源码发现,beego框架在启动时把所有的model信息存储在叫modelCache的全局变量里,这个变量里存了两种对应关系:
1. 表名–model info
2. model类型名–model info

modelCache = &_modelCache{
        cache:     make(map[string]*modelInfo),
        cacheByFN: make(map[string]*modelInfo),
    }

所以调QueryTable时要么传表名,要么传model实例,都可以找到对应的model info.

modelCache是什么时候存的内容了?在调orm.RegisterModel(new(SystemNickname))时。查看其源码发现,beego在找表名时是先相依相偎这个model有没有一个叫TableName的方法,有就用它的返回值作表名,没有就用它的类型名作表名。TableName在组装sql语句里也会用到,所以必须实现。

func registerModel(prefix string, model interface{}) {
    val := reflect.ValueOf(model)
    ind := reflect.Indirect(val)
    typ := ind.Type()

    if val.Kind() != reflect.Ptr {
        panic(fmt.Errorf("<orm.RegisterModel> cannot use non-ptr model struct `%s`", getFullName(typ)))
    }

    table := getTableName(val)

    if prefix != "" {
        table = prefix + table
    }
    name := getFullName(typ)
    if _, ok := modelCache.getByFN(name); ok {
        fmt.Printf("<orm.RegisterModel> model `%s` repeat register, must be unique\n", name)
        os.Exit(2)
    }

    if _, ok := modelCache.get(table); ok {
        fmt.Printf("<orm.RegisterModel> table name `%s` repeat register, must be unique\n", table)
        os.Exit(2)
    }

    info := newModelInfo(val)

    if info.fields.pk == nil {
    outFor:
        for _, fi := range info.fields.fieldsDB {
            if fi.name == "Id" {
                if fi.sf.Tag.Get(defaultStructTagName) == "" {
                    switch fi.addrValue.Elem().Kind() {
                    case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64:
                        fi.auto = true
                        fi.pk = true
                        info.fields.pk = fi
                        break outFor
                    }
                }
            }
        }

        if info.fields.pk == nil {
            fmt.Printf("<orm.RegisterModel> `%s` need a primary key field\n", name)
            os.Exit(2)
        }

    }

    info.table = table
    info.pkg = typ.PkgPath()
    info.model = model
    info.manual = true

    modelCache.set(table, info)
}

总之,只要做到三点,调QueryTable就不会出错了:
1. 实现model类的TableName方法,返回其在数据库中的真实表名(不能有大写)
2. 调用RegisterModel注册
3. QueryTable参数传model实例

实验环境:
bee :1.3.0
beego :1.5.0
Go :go version go1.5.2 windows/amd64

未经允许,不得转载本站任何文章:代码山 » Beego的QueryTable

分享到:更多 ()

专注品牌化高端网站建设

商务服务联系我们