
TORM 采用 Active Record 模式的模型系统,让你可以用面向对象的方式操作数据库。每个模型对应一个数据库表,模型实例对应表中的一行记录。
📋 目录
🚀 快速开始
基础模型定义
package models
import (
"time"
"github.com/zhoudm1743/torm/pkg/model"
)
type User struct {
model.BaseModel
ID interface{} `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
Age int `json:"age" db:"age"`
Status string `json:"status" db:"status"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
func NewUser() *User {
user := &User{
BaseModel: *model.NewBaseModel(),
}
user.SetTable("users")
user.SetConnection("default")
return user
}
📊 模型定义
字段标签
type User struct {
model.BaseModel
ID int64 `json:"id" db:"id" primary:"true"`
Name string `json:"name" db:"name" validate:"required"`
Email string `json:"email" db:"email" unique:"true"`
Password string `json:"-" db:"password"`
Profile string `json:"profile" db:"profile" type:"json"`
Avatar *string `json:"avatar" db:"avatar"`
CreatedAt time.Time `json:"created_at" db:"created_at" auto:"true"`
}
表名约定
type User struct { }
type BlogPost struct { }
func (u *User) TableName() string {
return "custom_users"
}
func NewUser() *User {
user := &User{BaseModel: *model.NewBaseModel()}
user.SetTable("users")
return user
}
连接配置
user.SetConnection("mysql")
user.SetConnection("default")
type User struct { }
type Log struct { }
func NewLog() *Log {
log := &Log{BaseModel: *model.NewBaseModel()}
log.SetConnection("log_db")
return log
}
🎯 基础操作
创建记录
user := NewUser()
user.Name = "张三"
user.Email = "zhangsan@example.com"
user.Age = 25
err := user.Save()
user := NewUser()
err := user.Fill(map[string]interface{}{
"name": "李四",
"email": "lisi@example.com",
"age": 30,
}).Save()
user := NewUser()
err := user.Create(map[string]interface{}{
"name": "王五",
"email": "wangwu@example.com",
"age": 28,
})
查找记录
user := NewUser()
err := user.Find(1)
user := NewUser()
err := user.First()
user := NewUser()
err := user.Where("email", "=", "user@example.com").First()
user := NewUser()
err := user.FindOrFail(1)
更新记录
user := NewUser()
err := user.Find(1)
if err == nil {
user.Name = "新名字"
user.Age = 26
err = user.Save()
}
user := NewUser()
err := user.Where("id", "=", 1).Update(map[string]interface{}{
"name": "更新的名字",
"age": 27,
})
user := NewUser()
affected, err := user.Where("status", "=", "inactive").
Update(map[string]interface{}{
"status": "archived",
})
删除记录
user := NewUser()
err := user.Find(1)
if err == nil {
err = user.Delete()
}
user := NewUser()
affected, err := user.Where("status", "=", "inactive").Delete()
user := NewUser()
affected, err := user.WhereIn("id", []interface{}{1, 2, 3}).Delete()
🔍 查询方法
基础查询
user := NewUser()
users, err := user.All()
users, err := user.Where("age", ">", 18).
Where("status", "=", "active").
Get()
users, err := user.OrderBy("created_at", "desc").Get()
users, err := user.Limit(10).Get()
result, err := user.Paginate(1, 10)
聚合查询
user := NewUser()
count, err := user.Where("status", "=", "active").Count()
exists, err := user.Where("email", "=", "test@example.com").Exists()
maxAge, err := user.Max("age")
minAge, err := user.Min("age")
totalAge, err := user.Sum("age")
avgAge, err := user.Avg("age")
高级查询
user := NewUser()
users, err := user.WhereRaw("YEAR(created_at) = ?", 2023).Get()
users, err := user.WhereExists(func(q db.QueryInterface) db.QueryInterface {
return q.Table("orders").
Where("orders.user_id", "=", "users.id").
Where("orders.status", "=", "completed")
}).Get()
users, err := user.
LeftJoin("profiles", "profiles.user_id", "=", "users.id").
Select("users.*", "profiles.avatar").
Get()
💼 属性管理
属性访问
user := NewUser()
err := user.Find(1)
name := user.GetAttribute("name")
email := user.GetAttribute("email")
user.SetAttribute("name", "新名字")
user.SetAttribute("age", 30)
user.SetAttributes(map[string]interface{}{
"name": "批量设置的名字",
"age": 35,
})
attributes := user.GetAttributes()
脏数据检测
user := NewUser()
err := user.Find(1)
user.Name = "新名字"
user.Age = 30
isDirty := user.IsDirty()
isDirtyName := user.IsDirty("name")
isDirtyEmail := user.IsDirty("email")
dirty := user.GetDirty()
original := user.GetOriginal("name")
属性转换
type User struct {
model.BaseModel
}
func (u *User) GetNameAttribute() string {
name := u.GetAttribute("name")
if name == nil {
return ""
}
return strings.ToUpper(name.(string))
}
func (u *User) SetPasswordAttribute(password string) {
hashedPassword := hashPassword(password)
u.SetAttribute("password", hashedPassword)
}
🎣 事件钩子
生命周期钩子
type User struct {
model.BaseModel
}
func (u *User) BeforeSave() error {
if u.GetAttribute("email") == "" {
return errors.New("邮箱不能为空")
}
return nil
}
func (u *User) AfterSave() error {
log.Printf("用户 %s 已保存", u.GetAttribute("name"))
return nil
}
func (u *User) BeforeCreate() error {
u.SetAttribute("status", "active")
return nil
}
func (u *User) AfterCreate() error {
return u.createUserProfile()
}
func (u *User) BeforeUpdate() error {
u.SetAttribute("updated_at", time.Now())
return nil
}
func (u *User) AfterUpdate() error {
return clearUserCache(u.GetKey())
}
func (u *User) BeforeDelete() error {
if u.GetAttribute("status") == "admin" {
return errors.New("管理员用户不能删除")
}
return nil
}
func (u *User) AfterDelete() error {
return u.cleanupUserData()
}
查找钩子
func (u *User) AfterFind() error {
return nil
}
⏰ 时间戳
自动时间戳
type User struct {
model.BaseModel
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
func NewUser() *User {
user := &User{BaseModel: *model.NewBaseModel()}
user.SetTable("users")
user.EnableTimestamps()
user.SetCreatedAtColumn("created_at")
user.SetUpdatedAtColumn("updated_at")
return user
}
禁用时间戳
user := NewUser()
user.DisableTimestamps()
user.WithoutTimestamps(func() error {
return user.Save()
})
🗑️ 软删除
启用软删除
type User struct {
model.BaseModel
DeletedAt *time.Time `json:"deleted_at" db:"deleted_at"`
}
func NewUser() *User {
user := &User{BaseModel: *model.NewBaseModel()}
user.SetTable("users")
user.EnableSoftDeletes()
user.SetDeletedAtColumn("deleted_at")
return user
}
软删除操作
user := NewUser()
err := user.Find(1)
err = user.Delete()
users, err := user.Where("status", "=", "active").Get()
users, err := user.WithTrashed().Get()
users, err := user.OnlyTrashed().Get()
err = user.Find(1)
err = user.WithTrashed().Find(1)
err = user.Restore()
err = user.WithTrashed().Find(1)
err = user.ForceDelete()
🔑 自定义主键
UUID主键
type Product struct {
model.BaseModel
UUID string `json:"uuid" db:"uuid" primary:"true"`
Name string `json:"name" db:"name"`
Price float64 `json:"price" db:"price"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
func NewProduct() *Product {
product := &Product{BaseModel: *model.NewBaseModel()}
product.SetTable("products")
product.DetectPrimaryKeysFromStruct(product)
return product
}
复合主键
type UserRole struct {
model.BaseModel
TenantID string `json:"tenant_id" db:"tenant_id" primary:"true"`
UserID string `json:"user_id" db:"user_id" primary:"true"`
Role string `json:"role" db:"role"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
func NewUserRole() *UserRole {
userRole := &UserRole{BaseModel: *model.NewBaseModel()}
userRole.SetTable("user_roles")
userRole.DetectPrimaryKeysFromStruct(userRole)
return userRole
}
userRole := NewUserRole()
userRole.SetAttribute("tenant_id", "tenant-001")
userRole.SetAttribute("user_id", "user-001")
userRole.SetAttribute("role", "admin")
err := userRole.Save()
userRole2 := NewUserRole()
userRole2.SetAttribute("tenant_id", "tenant-001")
userRole2.SetAttribute("user_id", "user-001")
err = userRole2.Find()
🎯 作用域
定义作用域
type User struct {
model.BaseModel
}
func (u *User) ScopeActive(query db.QueryInterface) db.QueryInterface {
return query.Where("status", "=", "active")
}
func (u *User) ScopeAdult(query db.QueryInterface) db.QueryInterface {
return query.Where("age", ">=", 18)
}
func (u *User) ScopeByCity(query db.QueryInterface, city string) db.QueryInterface {
return query.Where("city", "=", city)
}
使用作用域
user := NewUser()
users, err := user.Active().Get()
users, err := user.Active().Adult().Get()
users, err := user.Active().ByCity("北京").Get()
users, err := user.Active().
Where("vip_level", ">", 3).
OrderBy("created_at", "desc").
Get()
全局作用域
type User struct {
model.BaseModel
}
func NewUser() *User {
user := &User{BaseModel: *model.NewBaseModel()}
user.SetTable("users")
user.AddGlobalScope("active", func(query db.QueryInterface) db.QueryInterface {
return query.Where("status", "!=", "deleted")
})
return user
}
user := NewUser()
users, err := user.WithoutGlobalScope("active").Get()
📤 序列化
JSON序列化
user := NewUser()
err := user.Find(1)
jsonData, err := user.ToJSON()
userData := user.ToMap()
type User struct {
model.BaseModel
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"-"`
Secret string `json:"secret,omitempty"`
}
自定义序列化
type User struct {
model.BaseModel
}
func (u *User) Serialize() map[string]interface{} {
return map[string]interface{}{
"id": u.GetAttribute("id"),
"name": u.GetAttribute("name"),
"email": u.GetAttribute("email"),
"avatar_url": u.getAvatarURL(),
"is_admin": u.isAdmin(),
}
}
func (u *User) getAvatarURL() string {
avatar := u.GetAttribute("avatar")
if avatar == nil {
return "/default-avatar.png"
}
return "/avatars/" + avatar.(string)
}
func (u *User) isAdmin() bool {
role := u.GetAttribute("role")
return role == "admin"
}
🔧 高级功能
模型工厂
func UserFactory() *User {
user := NewUser()
user.Fill(map[string]interface{}{
"name": "测试用户",
"email": fmt.Sprintf("test%d@example.com", rand.Int()),
"age": rand.Intn(50) + 18,
"status": "active",
})
return user
}
func CreateTestUsers(count int) error {
for i := 0; i < count; i++ {
user := UserFactory()
if err := user.Save(); err != nil {
return err
}
}
return nil
}
模型观察者
type UserObserver struct{}
func (o *UserObserver) Creating(user *User) error {
return nil
}
func (o *UserObserver) Created(user *User) error {
log.Printf("新用户创建: %s", user.GetAttribute("name"))
return nil
}
func init() {
model.RegisterObserver(&User{}, &UserObserver{})
}
📚 最佳实践
1. 模型结构设计
type User struct {
model.BaseModel
ID int64 `json:"id" db:"id" primary:"true"`
Name string `json:"name" db:"name" validate:"required"`
Email string `json:"email" db:"email" validate:"required,email" unique:"true"`
Status string `json:"status" db:"status" default:"active"`
IsActive bool `json:"is_active" db:"is_active" default:"true"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
DeletedAt *time.Time `json:"deleted_at" db:"deleted_at"`
}
2. 错误处理
func CreateUser(userData map[string]interface{}) (*User, error) {
user := NewUser()
if err := validateUserData(userData); err != nil {
return nil, fmt.Errorf("数据验证失败: %w", err)
}
user.Fill(userData)
if err := user.Save(); err != nil {
return nil, fmt.Errorf("保存用户失败: %w", err)
}
return user, nil
}
3. 性能优化
users, err := user.Select("id", "name", "email").
Where("status", "=", "active").
Limit(100).
Get()
result, err := user.Where("status", "=", "active").
Paginate(page, 20)
users, err := user.Where("email", "=", email).
Where("status", "=", "active").
Get()