beego的orm模型定义学习与实际测试

本文介绍了beego ORM的学习,包括参数设置如忽略字段、自增键、索引等,以及表关系设置如一对一、一对多、多对多关系。详细探讨了如何查询,如关系查询、QueryTable的使用,以及事物处理和复杂查询的构造。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

beego中的orm学习

标签:beego orm

因为我没怎么用过orm,一般就直接用着sql驱动直接上了。数据库上的也有一段时间了,对于各种关系忘得也是差不多了。

这里主要是官方写的不是特别好,比如官方中文文档在这里给出的models.go的例子,让人看的很迷茫。

package main

import (
    "github.com/astaxie/beego/orm"
)

type User struct {
    Id          int
    Name        string
    Profile     *Profile   `orm:"rel(one)"` // OneToOne relation
    Post        []*Post `orm:"reverse(many)"` // 设置一对多的反向关系
}

type Profile struct {
    Id          int
    Age         int16
    User        *User   `orm:"reverse(one)"` // 设置一对一反向关系(可选)
}

type Post struct {
    Id    int
    Title string
    User  *User  `orm:"rel(fk)"`    //设置一对多关系
    Tags  []*Tag `orm:"rel(m2m)"`
}

type Tag struct {
    Id    int
    Name  string
    Posts []*Post `orm:"reverse(many)"`
}

func init() {
    // 需要在init中注册定义的model
    orm.RegisterModel(new(User), new(Post), new(Profile), new(Tag))
}

这……我知道那些标签能够用反射获得,可是orm后面的那些什么一对一、一对多关系都是什么东西?下面将记录一些我在orm学习的一些坑点,以及数据库知识与orm知识的回顾与结合。

参数设置

orm中的参数设置,比如rel、default之类的,定义在官方文档的模型定义这里。模型定义功能主要用于数据库数据转换和自动建表,对于我这种比较喜欢把所有相关的语句放在一个地方,同时又不想写SQL语句的人而言,这个功能还是值得深入研究的。(毕竟能够在本语言内解决的东西最好还是不要再加技术栈)

设置参数:orm:"null;rel(fk)",多个设置之间使用;进行分隔。设置的值如果是多个,使用,进行分隔。

忽略字段

设置-可忽略struct中的字段,比如

type User struct {
...
    AnyField string `orm:"-"`
...
}

auto

当Field类型为int等类型的时候,可以设置字段为自增键(extra:auto_increment)。当模型定义中没有主键时,符合上述类型且名称为Id的Field将被视为自增键。

pk

primary key,设置为逐渐。适用于定义其他名称与类型为主键。

null

数据库表默认为NOT NULL,设置null代表允许,即ALLOW NULL,比如Name string orm:"null"

index

为单个字段增加索引(模型定义的开头有提到复合索引)

unique

为单个字段增加unique键

column

为字段设置db字段的名称(不设置将会自动转换,转换规则也是在模型定义页面的开头)。

    Name string `orm:"column(user_name)"`

size

string类型默认为varchar(255),设置size之后会变为varchar(size)

    Title string `orm:"size(60)"`

digits/decimals

设置float32,float64类型的浮点精度

    Money float64 `orm:"digits(12);decimals(4)"`

即总长度12,小数点后4位

auto_now/auto_now_add

    Created time.Time `orm:"auto_now_add;type(datetime)"`
    Updated time.Time `orm:"auto_now;type(datetime)"`
  • auto_now每次model保存时都会对时间自动更新
  • auto_now_add第一次保存时才设置时间

对于批量的update此设置是不生效的。

type

设置为date时,time.Time字段的对应db类型使用date。设置为datetime时,time.Time字段的对应db类型使用datetime

default

为字段设置默认值,类型必须符合(目前仅用于级联删除时的默认值)

Comment

    type User struct {
        ...
        Status int `orm:"default(1)" description:(这是状态字段)`
        ...
    }

为字段添加注释,注释中禁止包含引号

表关系设置

rel/reverse

关系参考了Django ORM 一对一、一对多、多对多详解,例子使用的是官方中文教程的例子。

一对一关系

子表从母表中选出一条数据一一对应,母表中选出来一条就少一条,子表中不可以再选择母表中已经选择的数据。

从数学的角度上来说,就是将子表作为定义域,母表作为值域的单射(不确定是否是满射,好像可以不是的样子)

RelOneToOne:

type User struct {
    ...
    Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
    ...
}

对应的反向关系RelReverseOne

type Profile struct {
    ...
    User *User `orm:"reverse(one)"`
    ...
}

实验打出来的表格信息:

create table `user`
    -- --------------------------------------------------
    --  Table Structure for `main.User`
    -- --------------------------------------------------
    CREATE TABLE IF NOT EXISTS `user` (
        `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
        `profile_id` integer UNIQUE
    ) ENGINE=InnoDB;

create table `profile`
    -- --------------------------------------------------
    --  Table Structure for `main.Profile`
    -- --------------------------------------------------
    CREATE TABLE IF NOT EXISTS `profile
### RK3588平台NPU调用方法 #### 创建和初始化NPU环境 为了在RK3588平台上成功调用NPU进行神经网络推理或加速,首先需要确保设备已正确配置并加载了相应的驱动程序。Rockchip的官方固件通常已经预装了RKNPU驱动[^3]。 一旦确认硬件准备就绪,可以通过以下方式创建和初始化NPU环境: ```cpp #include "rknn_api.h" // 初始化模型路径和其他参数 const char* model_path = "./model.rknn"; int ret; rknn_context ctx; ret = rknn_init(&ctx, model_path, 0, 0, NULL); if (ret < 0) { printf("Failed to initialize rknn context\n"); } ``` 这段代码展示了如何使用`rknn_api.h`库来初始化一个RKNN上下文对象,这一步骤对于后续的操作至关重要[^2]。 #### 加载和编译模型 接下来,在实际运行之前还需要加载预先训练好的神经网络模型文件(通常是`.rknn`格式)。此过程涉及读取模型二进制数据,并将其传递给RKNN API以便内部处理和优化。 ```cpp // 假设模型已经被转换成 .rknn 文件格式 char *model_data; // 模型的数据指针 size_t model_size; // 模型大小 FILE *fp = fopen(model_path, "rb+"); fseek(fp, 0L, SEEK_END); model_size = ftell(fp); rewind(fp); model_data = (char *)malloc(sizeof(char)*model_size); fread(model_data, sizeof(unsigned char), model_size, fp); fclose(fp); // 将模型数据传入RKNN API ret = rknn_load_rknn(ctx, &model_data, &model_size); free(model_data); if(ret != 0){ printf("Load Model Failed!\n"); } else{ printf("Model Loaded Successfully.\n"); } ``` 这里说明了从磁盘读取模型文件的具体操作流程,并通过API函数将这些信息提交给了底层框架去解析和设置好用于推断所需的资源[^1]。 #### 执行前向传播计算 当一切准备工作完成后就可以开始真正的预测工作——即让NPU执行一次完整的前向传播运算。这个阶段主要是构建输入张量、启动异步任务以及收集输出结果。 ```cpp float input_tensor[INPUT_SIZE]; // 输入特征图数组 float output_tensors[MAX_OUTPUTS][OUTPUT_SIZE]; // 输出特征图数组 struct rknn_input inputs[] = {{input_tensor}}; struct rknn_output outputs[MAX_OUTPUTS]; for(int i=0;i<NUM_ITERATIONS;++i){ memset(inputs, 0 ,sizeof(struct rknn_input)); memcpy(input_tensor, inputData[i], INPUT_SIZE*sizeof(float)); // 启动推理任务 ret = rknn_run(ctx, nullptr); if(ret!=0){ printf("Inference failed at iteration %d", i); break; } // 获取输出结果 for(size_t j=0;j<num_outputs;++j){ struct rknn_output& out = outputs[j]; size_t bufSize = OUTPUT_SIZE * sizeof(float); void* buffer = malloc(bufSize); ret = rknn_get_output(ctx, j, &out.datatype, &buffer, &bufSize, false); if(!ret && buffer){ memcpy(output_tensors[j], buffer, bufSize); free(buffer); } } } printf("All iterations completed successfully."); ``` 上述片段体现了典型的基于RKNN SDK的应用场景:先准备好待测样本作为输入;接着触发内核中的计算逻辑;最后获取到经过变换后的响应值供下一步分析所用[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值