Skip to content

定义模型

VEF Framework 使用 Bun ORM 进行数据库操作。所有模型应嵌入 orm.Model 以获得自动审计字段管理。

基本模型定义

go
package models

import (
    "github.com/ilxqx/vef-framework-go/orm"
    "github.com/ilxqx/vef-framework-go/null"
)

// User represents a user entity in the database
type User struct {
    orm.Model
    Username    string      `bun:"username,notnull,unique" json:"username"`
    Email       string      `bun:"email,notnull,unique" json:"email"`
    Password    string      `bun:"password,notnull" json:"-"`
    DisplayName null.String `bun:"display_name" json:"displayName"`
    IsActive    bool        `bun:"is_active,notnull,default:true" json:"isActive"`
    Age         null.Int    `bun:"age" json:"age"`
}

orm.Model 结构

orm.Model 提供了通用的审计字段:

go
// orm.Model provides common audit fields
type Model struct {
    Id        string      `bun:"id,pk" json:"id"`
    CreatedAt time.Time   `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"`
    CreatedBy null.String `bun:"created_by" json:"createdBy"`
    UpdatedAt time.Time   `bun:"updated_at,notnull,default:current_timestamp" json:"updatedAt"`
    UpdatedBy null.String `bun:"updated_by" json:"updatedBy"`
}

审计字段说明

字段数据库列JSON 字段说明
Ididid主键,自动生成 UUID
CreatedAtcreated_atcreatedAt创建时间,自动设置
CreatedBycreated_bycreatedBy创建人 ID,自动设置
UpdatedAtupdated_atupdatedAt更新时间,自动更新
UpdatedByupdated_byupdatedBy更新人 ID,自动设置

命名约定

  • 数据库列使用 snake_case(如 created_at
  • JSON 字段使用 camelCase(如 createdAt

完整模型示例

用户模型

go
package models

import (
    "github.com/ilxqx/vef-framework-go/orm"
    "github.com/ilxqx/vef-framework-go/null"
)

// User represents a system user
type User struct {
    orm.Model
    
    // Basic information
    Username    string      `bun:"username,notnull,unique" json:"username"`
    Email       string      `bun:"email,notnull,unique" json:"email"`
    Password    string      `bun:"password,notnull" json:"-"`
    
    // Profile information
    DisplayName null.String `bun:"display_name" json:"displayName"`
    Avatar      null.String `bun:"avatar" json:"avatar"`
    Phone       null.String `bun:"phone" json:"phone"`
    
    // Status
    IsActive    bool        `bun:"is_active,notnull,default:true" json:"isActive"`
    LastLoginAt null.Time   `bun:"last_login_at" json:"lastLoginAt"`
    
    // Relations (not stored in database)
    Roles       []Role      `bun:"rel:has-many,join:id=user_id" json:"roles,omitempty"`
}

订单模型

go
package models

import (
    "github.com/ilxqx/vef-framework-go/orm"
    "github.com/ilxqx/vef-framework-go/null"
    "github.com/shopspring/decimal"
)

// Order represents a customer order
type Order struct {
    orm.Model
    
    // Order information
    OrderNo     string          `bun:"order_no,notnull,unique" json:"orderNo"`
    CustomerId  string          `bun:"customer_id,notnull" json:"customerId"`
    
    // Amount
    TotalAmount decimal.Decimal `bun:"total_amount,notnull,type:decimal(10,2)" json:"totalAmount"`
    Discount    decimal.Decimal `bun:"discount,notnull,default:0,type:decimal(10,2)" json:"discount"`
    
    // Status
    Status      string          `bun:"status,notnull,default:'pending'" json:"status"`
    PaidAt      null.Time       `bun:"paid_at" json:"paidAt"`
    
    // Shipping
    ShippingAddress null.String `bun:"shipping_address" json:"shippingAddress"`
    ShippedAt       null.Time   `bun:"shipped_at" json:"shippedAt"`
    
    // Relations
    Customer    *User           `bun:"rel:belongs-to,join:customer_id=id" json:"customer,omitempty"`
    Items       []OrderItem     `bun:"rel:has-many,join:id=order_id" json:"items,omitempty"`
}

树形结构模型

go
package models

import (
    "github.com/ilxqx/vef-framework-go/orm"
    "github.com/ilxqx/vef-framework-go/null"
)

// Department represents an organization department with tree structure
type Department struct {
    orm.Model
    
    // Basic information
    Name        string      `bun:"name,notnull" json:"name"`
    Code        string      `bun:"code,notnull,unique" json:"code"`
    
    // Tree structure
    ParentId    null.String `bun:"parent_id" json:"parentId"`
    SortOrder   int         `bun:"sort_order,notnull,default:0" json:"sortOrder"`
    
    // Status
    IsActive    bool        `bun:"is_active,notnull,default:true" json:"isActive"`
    
    // Tree relations (not stored, populated by FindTreeApi)
    Children    []Department `bun:"-" json:"children,omitempty"`
}

模型关系

一对多关系

go
// User has many orders
type User struct {
    orm.Model
    Username string  `bun:"username,notnull" json:"username"`
    Orders   []Order `bun:"rel:has-many,join:id=user_id" json:"orders,omitempty"`
}

// Order belongs to user
type Order struct {
    orm.Model
    UserId string `bun:"user_id,notnull" json:"userId"`
    User   *User  `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
}

多对多关系

go
// User has many roles through user_roles table
type User struct {
    orm.Model
    Username string `bun:"username,notnull" json:"username"`
    Roles    []Role `bun:"m2m:user_roles,join:User=Role" json:"roles,omitempty"`
}

// Role has many users through user_roles table
type Role struct {
    orm.Model
    Name  string `bun:"name,notnull" json:"name"`
    Users []User `bun:"m2m:user_roles,join:Role=User" json:"users,omitempty"`
}

// UserRole is the join table
type UserRole struct {
    UserId string `bun:"user_id,pk"`
    RoleId string `bun:"role_id,pk"`
}

表名自定义

默认情况下,表名是模型名的复数形式(snake_case)。可以通过实现 TableName 方法自定义:

go
// Custom table name
func (u *User) TableName() string {
    return "sys_users"
}

索引定义

使用 bun 标签定义索引:

go
type User struct {
    orm.Model
    Username string `bun:"username,notnull,unique"`                    // Unique index
    Email    string `bun:"email,notnull,unique:idx_user_email"`        // Named unique index
    Status   string `bun:"status,notnull"`
    Type     string `bun:"type,notnull"`
    
    // Composite index defined via table option
    _ struct{} `bun:"table:users,alias:u,index:idx_status_type(status,type)"`
}

软删除

VEF Framework 支持软删除,通过 DeletedAt 字段实现:

go
type User struct {
    orm.Model
    orm.SoftDelete  // Adds DeletedAt field
    Username string `bun:"username,notnull" json:"username"`
}

软删除后,记录不会从数据库中物理删除,而是设置 deleted_at 字段。查询时会自动过滤已删除的记录。

下一步

基于 Apache License 2.0 许可发布