XOrm

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2025 License: MIT Imports: 25 Imported by: 0

README

XOrm

Reference Release Report DeepWiki

XOrm 拓展了 Beego 的 ORM 功能,同时实现了基于上下文的事务机制,提高了数据操作的效率。

功能特性

  • 多源配置:通过首选项中的配置自动初始化数据库连接
  • 数据模型:提供了面向对象的模型设计及常用的数据操作
  • 事务操作:基于上下文的事务机制,支持缓存和并发控制

使用手册

1. 多源配置

通过解析首选项中的配置自动初始化数据库连接。

配置说明:

  • 配置键名:Orm/Source/<数据库类型>/<数据库别名>
    • 支持 MySQL、PostgreSQL、SQLite3 等(Beego ORM 支持的类型)
  • 配置参数:
    • Addr:数据源地址
    • Pool:连接池大小
    • Conn:最大连接数

配置示例:

{
    "Orm/Source/MySQL/Main": {
        "Addr": "root:123456@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&loc=Local",
        "Pool": 1,
        "Conn": 1
    },
    "Orm/Source/PostgreSQL/Log": {
        "Addr": "postgres://user:pass@localhost:5432/dbname?sslmode=disable",
        "Pool": 2,
        "Conn": 10
    },
    "Orm/Source/SQLite3/Type": {
        "Addr": "file:data.db?cache=shared&mode=rwc",
        "Pool": 1,
        "Conn": 1
    }
}
2. 数据模型

提供了面向对象的模型设计及常用的数据操作。

2.1 模型定义
// 定义用户模型
type User struct {
    XOrm.Model[User]           // 继承基础模型
    ID        int        `orm:"column(id);pk"` // 主键字段
    Name      string     `orm:"column(name)"` // 字符串字段
    Age       int        `orm:"column(age)"` // 整型字段
}

// 实现必要的接口方法
func (u *User) AliasName() string {
    return "mydb" // 数据库别名
}

func (u *User) TableName() string {
    return "user" // 数据库表名
}

// 创建模型实例的工厂方法
func NewUser() *User {
    return XObject.New[User]()
}
2.2 模型接口

模型接口定义了以下核心方法:

  1. 生命周期:
Ctor(obj any)                                               // 构造初始化
OnEncode()                                                  // 编码前回调
OnDecode()                                                  // 解码后回调
OnQuery(action string, cond *orm.Condition) *orm.Condition  // 查询时回调
  1. 基础信息:
AliasName() string          // 数据库别名
TableName() string          // 数据表名称
ModelUnique() string        // 模型标识
DataUnique() string         // 数据标识
DataValue(field string) any // 获取字段值
  1. 数据操作:
Read(cond ...*condition) bool                  // 读取数据
List(rets any, cond ...*condition) int         // 列举数据
Write() int                                    // 写入数据
Delete() int                                   // 删除数据
Clear(cond ...*condition) int                  // 清除数据
Count(cond ...*condition) int                  // 统计数量
Max(column ...string) int                      // 获取最大值
Min(column ...string) int                      // 获取最小值
  1. 工具方法:
IsValid(value ...bool) bool // 检查/设置有效性
Clone() IModel             // 深度拷贝
Json() string              // JSON序列化
Equals(model IModel) bool  // 对象比较
Matchs(cond ...*condition) bool // 条件匹配
2.3 模型注册

参数说明:

  • cache:是否缓存,启用后支持全局缓存
  • writable:是否可写,启用后支持修改数据

应用场景:

是否缓存 是否可写 应用场景
true true 适用于高频读取、写入且数据规模可控的模型,如用户信息等。
true false 适用于高频读取、无需写入的模型,如只读配置等。
false true 适用于高频写入,低频读取或者数据规模不可控的场景,如日志记录等。

注意:选择参数时除了考虑应用场景外,还需结合实际业务运行情况,如是否存在多个实例同时读写的情况。

示例代码:

// 用户模型:高频读取、写入且数据规模可控
// cache=true, writable=true
XOrm.Meta(NewUser(), true, true)

// 配置模型:高频读取、无需写入
// cache=true, writable=false
XOrm.Meta(NewConfig(), true, false)

// 日志模型:高频写入,低频读取或者数据规模不可控
// cache=false, writable=true
XOrm.Meta(NewLog(), false, true)
2.4 条件查询

支持多种查询方式和复杂的条件组合。

2.4.1 创建条件
// 1. 创建空条件
cond := XOrm.Cond()

// 2. 从现有条件创建
cond := XOrm.Cond(orm.NewCondition())

// 3. 从表达式创建(推荐)
cond := XOrm.Cond("age > {0} && name == {1}", 18, "test")
2.4.2 比较运算符
// 大于/大于等于
cond := XOrm.Cond("age > {0}", 18)  // age__gt
cond := XOrm.Cond("age >= {0}", 18) // age__gte

// 小于/小于等于
cond := XOrm.Cond("age < {0}", 18)  // age__lt
cond := XOrm.Cond("age <= {0}", 18) // age__lte

// 等于/不等于
cond := XOrm.Cond("age == {0}", 18) // age__exact
cond := XOrm.Cond("age != {0}", 18) // age__ne

// 空值判断
cond := XOrm.Cond("age isnull {0}", true) // age__isnull
2.4.3 字符串匹配
// 包含
cond := XOrm.Cond("name contains {0}", "test") // name__contains

// 前缀匹配
cond := XOrm.Cond("name startswith {0}", "test") // name__startswith

// 后缀匹配
cond := XOrm.Cond("name endswith {0}", "test") // name__endswith
2.4.4 逻辑组合
// AND 组合
cond := XOrm.Cond("age > {0} && name == {1}", 18, "test")

// OR 组合
cond := XOrm.Cond("age < {0} || age > {1}", 18, 60)

// NOT 条件
cond := XOrm.Cond("!(age >= {0})", 30)

// 复杂组合
cond := XOrm.Cond("(age >= {0} && age <= {1}) || name == {2}", 18, 30, "test")
cond := XOrm.Cond("((age > {0} && name contains {1}) || status == {2}) && active == {3}", 18, "test", "active", true)
2.4.5 分页查询
// 分页限定
cond := XOrm.Cond("age > {0} && limit = {1}", 18, 10)
// 分页偏移
cond := XOrm.Cond("age > {0} && offset = {1}", 18, 20)
// 组合使用
cond := XOrm.Cond("age > {0} && limit = {1} && offset = {2}", 18, 10, 20)
2.4.6 使用示例
// 1. 简单查询
model := NewUser()
cond := XOrm.Cond("age > {0}", 18)
user := model.Read(cond)
if user.IsValid() {
    fmt.Printf("Found user: %v\n", user.Name)
}

// 2. 复杂查询
model := NewUser()
var users []*User
cond := XOrm.Cond("(age >= {0} && age <= {1}) || name contains {2}", 18, 30, "test")
count := model.List(&users, cond)
fmt.Printf("Found %d users\n", count)

// 3. 分页查询
model := NewUser()
var users []*User
cond := XOrm.Cond("age > {0} && limit = {1} && offset = {2}", 18, 10, 20)
count := model.List(&users, cond)
fmt.Printf("Found %d users\n", count)

// 4. 统计查询
model := NewUser()
cond := XOrm.Cond("status == {0} && age > {1}", "active", 18)
count := model.Count(cond)
fmt.Printf("Found %d users\n", count)

注意事项:

  1. 条件表达式中的参数使用 {n} 形式引用,n 从 0 开始
  2. 参数数量必须与表达式中的占位符数量一致
  3. 复杂条件建议使用括号明确优先级
  4. 条件会被缓存以提高性能,相同的表达式只会解析一次
  5. 支持所有 Beego ORM 的条件操作符
3. 事务操作

基于上下文的事务机制,支持缓存和并发控制。

3.1 基本操作

所有数据操作都需要在会话监听的上下文中进行,以确保缓存策略和事务控制的正确性:

// 开始 CRUD 监控。
sid := XOrm.Watch()
// 结束 CRUD 监控。
defer XOrm.Defer()

// 写入操作:写入数据到会话缓存和全局缓存。
user := NewUser()
user.Name = "test"
user.Age = 18
XOrm.Write(user)

// 读取操作:按优先级依次从会话缓存、全局缓存、远端数据库读取。
user := NewUser()
user.ID = 1
if XOrm.Read(user) { // 精确查找,检查缓存标记。
    fmt.Printf("User: %v\n", user.Name)
}

// 条件读取:支持模糊查找和条件匹配。
cond := XOrm.Cond("age > {0}", 18)
if XOrm.Read(user, cond) { // 模糊查找,可能触发远端读取。
    fmt.Printf("User: %v\n", user.Name)
}

// 删除操作:标记删除状态。
XOrm.Delete(user) // 通过事务缓冲至提交队列中删除。

// 清除操作:标记清除状态
cond = XOrm.Cond("age < {0}", 18)
XOrm.Clear(user, cond) // 通过事务缓冲至提交队列中清除。

// 列举操作:从缓存和远端组合数据。
var users []*User
cond = XOrm.Cond("age > {0} && name contains {1}", 18, "test")
XOrm.List(&users, cond) // 依次检查会话缓存、全局缓存、远端数据。

注意:

  1. 所有操作必须在 Watch()Defer() 之间进行
  2. 写入操作会同时更新会话缓存和全局缓存
  3. 读取操作遵循缓存优先级:会话缓存 > 全局缓存 > 远端数据
  4. 删除和清理操作仅做标记,实际删除在会话提交时执行
  5. 列举操作可能会同时访问缓存和远端数据
3.2 指标监控

支持 Prometheus 指标监控,可以实时监控 CRUD 提交的性能和资源使用情况:

指标 类型 描述
xorm_commit_queue Gauge 所有队列中等待提交的对象总数
xorm_commit_total Counter 所有队列已经提交的对象总数
xorm_commit_queue_{n} Gauge 第 n 个队列中等待提交的对象数量
xorm_commit_total_{n} Counter 第 n 个队列已经提交的对象总数
3.3 可选配置

支持通过首选项配置对提交队列进行调整:

配置参数:

  • Orm/Commit/Queue:提交队列的数量,默认为 CPU 核心数,-1 表示禁用提交队列
  • Orm/Commit/Queue/Capacity:单个队列的容量,默认为 100000

配置示例:

{
    "Orm/Commit/Queue": 8,
    "Orm/Commit/Queue/Capacity": 100000
}
3.4 运行机理
stateDiagram-v2
    direction LR
    [*] --> Init: 初始化
    Init --> Run: 开始运行
    Run --> Watch: 监听会话
    Watch --> CRUD: 开始 CRUD 监听
    CRUD --> Defer: 结束 CRUD 监听
    Run --> Close: 退出信号

    state Init {
        direction TB
        [*] --> orm.RegisterDataBase: 解析配置选项
        orm.RegisterDataBase --> XOrm.Meta(): 注册数据模型
    }

    state Watch {
        direction TB
        [*] --> XOrm.Watch()
        XOrm.Watch() --> contextMap: 按 goroutine ID 记录上下文
    }

    state Defer {
        direction TB
        [*] --> XOrm.Defer()
        XOrm.Defer() --> 缓冲提交队列: 对比会话内存
        缓冲提交队列 --> 清除会话内存
        清除会话内存 --> [*]
    }

    state Flush(){
        direction TB
        [*] --> XOrm.Flush(): 刷新当前队列
        XOrm.Flush() --> 关闭提交队列
    }

    state Close{
        direction TB
        [*] --> Flush(): 刷新所有队列
        Flush() --> [*]
    }
   
    缓冲提交队列 --> 消费提交队列
    消费提交队列 --> 关闭提交队列: 收到退出信号
3.5 缓存策略
stateDiagram-v2
    direction TB
    state Context {
        同步缓存数据 --> [*]

        [*] --> XOrm.Read(): 数据读取操作
        XOrm.Read() --> 会话缓存读取: sessionListed
        会话缓存读取 --> 全局缓存读取: globalListed
        全局缓存读取 --> 远端数据读取: fallback
        远端数据读取 --> 同步缓存数据: data.IsValid(true)

        [*] --> XOrm.List(): 数据列举操作
        XOrm.List() --> 会话缓存列举: sessionListed
        会话缓存列举 --> 全局缓存列举: globalListed
        全局缓存列举 --> 远端数据列举: fallback
        远端数据列举 --> 同步缓存数据: datas.IsValid(true)

        [*] --> XOrm.Write(): 数据写入操作
        XOrm.Write() --> 同步缓存数据: data.IsValid(true) sobj.create = true

        [*] --> XOrm.Delete(): 数据删除操作
        XOrm.Delete() --> 同步缓存数据: data.IsValid(false) sobj.delete = true

        [*] --> XOrm.Clear(): 数据清除操作
        XOrm.Clear() --> 同步缓存数据: datas.IsValid(false) sobj.clear = cond

        [*] --> XOrm.Incre(): 索引自增操作
        XOrm.Incre() --> 同步缓存数据: globalIncreMap
    }

常见问题

1. 为什么要基于 Beego ORM 进行二次封装?

XOrm 模块基于 Beego ORM 封装了单实例的缓存及会话事务功能,主要面向的是游戏类低延迟、有状态的应用及业务场景。

具体来说,XOrm 相较于 Beego 等传统 ORM 框架提供了以下核心优势:

  1. 多级缓存机制:实现了会话缓存和全局缓存的双层缓存结构,大幅减少数据库访问频率

    • 会话缓存:在单个事务上下文中保持数据一致性
    • 全局缓存:跨会话共享频繁访问的数据
  2. 事务控制优化:

    • 延迟提交:通过批处理机制减少数据库连接压力
    • 软删除标记:先在缓存中标记删除,统一提交时执行实际删除操作
    • 并发控制:提供了队列机制处理并发写入
  3. 模型功能拓展:

    • 细粒度控制:通过 cachewritable 参数灵活配置模型特性
    • 多场景适配:针对不同业务场景(高频读写、只读配置、日志记录等)提供最优配置

这种封装特别适合游戏服务器等需要高性能、低延迟数据处理的场景,通过在内存中维护数据状态,最大限度减少数据库交互,同时保证数据一致性和可靠性。

2. XOrm 的查询性能如何?

以下是基于 100000 条本地数据(未计算网络延迟),XOrm.List(缓存查询) vs XOrm.Model.List(回源查询) 的性能测试结果:

CPU XOrm.List (ns/op) XOrm.Model.List (ns/op)
1 34.56 12.70
2 13.23 13.19
4 6.964 12.82
8 4.058 12.93
16 3.023 13.33
32 2.262 14.32

数据分析:

  1. XOrm.List 缓存查询操作随线程提升,耗时明显下降,性能表现优异。
  2. XOrm.List 多核环境下的查询性能优于 XOrm.Model.List 回源查询操作,性能表现优异。

更多问题,请查阅问题反馈

项目信息

Documentation

Overview

XOrm 拓展了 Beego 的 ORM 功能,同时实现了基于上下文的事务机制,提高了数据操作的效率。

功能特性

  • 多源配置:通过解析首选项中的配置自动初始化数据库连接
  • 数据模型:提供了面向对象的模型设计及常用的数据操作
  • 事务操作:基于上下文的事务机制,支持缓存和并发控制

使用手册

1. 多源配置

配置说明:

  • 配置键名:Orm/Source/<数据库类型>/<数据库别名>
  • 支持 MySQL、PostgreSQL、SQLite3 等(Beego ORM 支持的类型)
  • 配置参数:
  • Addr:数据源地址
  • Pool:连接池大小
  • Conn:最大连接数

配置示例:

{
    "Orm/Source/MySQL/Main": {
        "Addr": "root:123456@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&loc=Local",
        "Pool": 1,
        "Conn": 1
    },
    "Orm/Source/PostgreSQL/Log": {
        "Addr": "postgres://user:pass@localhost:5432/dbname?sslmode=disable",
        "Pool": 2,
        "Conn": 10
    },
    "Orm/Source/SQLite3/Type": {
        "Addr": "file:data.db?cache=shared&mode=rwc",
        "Pool": 1,
        "Conn": 1
    }
}

2. 数据模型

提供了面向对象的模型设计及常用的数据操作。

2.1 模型定义

// 定义用户模型
type User struct {
    XOrm.Model[User]           // 继承基础模型
    ID        int        `orm:"column(id);pk"` // 主键字段
    Name      string     `orm:"column(name)"` // 字符串字段
    Age       int        `orm:"column(age)"` // 整型字段
}

// 实现必要的接口方法
func (u *User) AliasName() string {
    return "mydb" // 数据库别名
}

func (u *User) TableName() string {
    return "user" // 数据库表名
}

// 创建模型实例的工厂方法
func NewUser() *User {
    return XObject.New[User]()
}

2.2 模型接口

模型接口定义了以下核心方法:

生命周期:

Ctor(obj any)                                               // 构造初始化
OnEncode()                                                  // 编码前回调
OnDecode()                                                  // 解码后回调
OnQuery(action string, cond *orm.Condition) *orm.Condition  // 查询时回调

基础信息:

AliasName() string          // 数据库别名
TableName() string          // 数据表名称
ModelUnique() string        // 模型标识
DataUnique() string         // 数据标识
DataValue(field string) any // 获取字段值

数据操作:

Read(cond ...*condition) bool                  // 读取数据
List(rets any, cond ...*condition) int         // 列举数据
Write() int                                    // 写入数据
Delete() int                                   // 删除数据
Clear(cond ...*condition) int                  // 清除数据
Count(cond ...*condition) int                  // 统计数量
Max(column ...string) int                      // 获取最大值
Min(column ...string) int                      // 获取最小值

工具方法:

IsValid(value ...bool) bool // 检查/设置有效性
Clone() IModel             // 深度拷贝
Json() string              // JSON序列化
Equals(model IModel) bool  // 对象比较
Matchs(cond ...*condition) bool // 条件匹配

2.3 模型注册

参数说明:

  • cache:是否缓存,启用后支持全局缓存
  • writable:是否可写,启用后支持修改数据

应用场景:

| 是否缓存 | 是否可写 | 应用场景 |
|---------|----------|---------|
| true    | true     | 适用于高频读取、写入且数据规模可控的模型,如用户信息等。 |
| true    | false    | 适用于高频读取、无需写入的模型,如只读配置等。 |
| false   | true     | 适用于高频写入,低频读取或者数据规模不可控的场景,如日志记录等。 |

注意:选择参数时除了考虑应用场景外,还需结合实际业务运行情况,如是否存在多个实例同时读写的情况。

示例代码:

// 用户模型:高频读取、写入且数据规模可控
// cache=true, writable=true
XOrm.Meta(NewUser(), true, true)

// 配置模型:高频读取、无需写入
// cache=true, writable=false
XOrm.Meta(NewConfig(), true, false)

// 日志模型:高频写入,低频读取或者数据规模不可控
// cache=false, writable=true
XOrm.Meta(NewLog(), false, true)

2.4 条件查询

支持多种查询方式和复杂的条件组合。

创建条件:

// 1. 创建空条件
cond := XOrm.Cond()

// 2. 从现有条件创建
cond := XOrm.Cond(orm.NewCondition())

// 3. 从表达式创建(推荐)
cond := XOrm.Cond("age > {0} && name == {1}", 18, "test")

比较运算符:

// 大于/大于等于
cond := XOrm.Cond("age > {0}", 18)  // age__gt
cond := XOrm.Cond("age >= {0}", 18) // age__gte

// 小于/小于等于
cond := XOrm.Cond("age < {0}", 18)  // age__lt
cond := XOrm.Cond("age <= {0}", 18) // age__lte

// 等于/不等于
cond := XOrm.Cond("age == {0}", 18) // age__exact
cond := XOrm.Cond("age != {0}", 18) // age__ne

// 空值判断
cond := XOrm.Cond("age isnull {0}", true) // age__isnull

字符串匹配:

// 包含
cond := XOrm.Cond("name contains {0}", "test") // name__contains

// 前缀匹配
cond := XOrm.Cond("name startswith {0}", "test") // name__startswith

// 后缀匹配
cond := XOrm.Cond("name endswith {0}", "test") // name__endswith

逻辑组合:

// AND 组合
cond := XOrm.Cond("age > {0} && name == {1}", 18, "test")

// OR 组合
cond := XOrm.Cond("age < {0} || age > {1}", 18, 60)

// NOT 条件
cond := XOrm.Cond("!(age >= {0})", 30)

// 复杂组合
cond := XOrm.Cond("(age >= {0} && age <= {1}) || name == {2}", 18, 30, "test")
cond := XOrm.Cond("((age > {0} && name contains {1}) || status == {2}) && active == {3}", 18, "test", "active", true)

分页查询:

// 分页限定
cond := XOrm.Cond("age > {0} && limit = {1}", 18, 10)

// 分页偏移
cond := XOrm.Cond("age > {0} && offset = {1}", 18, 20)

// 组合使用
cond := XOrm.Cond("age > {0} && limit = {1} && offset = {2}", 18, 10, 20)

使用示例:

// 1. 简单查询
model := NewUser()
cond := XOrm.Cond("age > {0}", 18)
user := model.Read(cond)
if user.IsValid() {
    fmt.Printf("Found user: %v\n", user.Name)
}

// 2. 复杂查询
model := NewUser()
var users []*User
cond := XOrm.Cond("(age >= {0} && age <= {1}) || name contains {2}", 18, 30, "test")
count := model.List(&users, cond)
fmt.Printf("Found %d users\n", count)

// 3. 分页查询
model := NewUser()
var users []*User
cond := XOrm.Cond("age > {0} && limit = {1} && offset = {2}", 18, 10, 20)
count := model.List(&users, cond)
fmt.Printf("Found %d users\n", count)

// 4. 统计查询
model := NewUser()
cond := XOrm.Cond("status == {0} && age > {1}", "active", 18)
count := model.Count(cond)
fmt.Printf("Found %d users\n", count)

注意事项: 1. 条件表达式中的参数使用 {n} 形式引用,n 从 0 开始 2. 参数数量必须与表达式中的占位符数量一致 3. 复杂条件建议使用括号明确优先级 4. 条件会被缓存以提高性能,相同的表达式只会解析一次 5. 支持所有 Beego ORM 的条件操作符

3. 事务操作

基于上下文的事务机制,支持缓存和并发控制。

3.1 基本操作

所有数据操作都需要在会话监听的上下文中进行,以确保缓存策略和事务控制的正确性:

// 开始 CRUD 监控。
sid := XOrm.Watch()
// 结束 CRUD 监控。
defer XOrm.Defer()

// 写入操作:写入数据到会话缓存和全局缓存。
user := NewUser()
user.Name = "test"
user.Age = 18
XOrm.Write(user)

// 读取操作:按优先级依次从会话缓存、全局缓存、远端数据库读取。
user := NewUser()
user.ID = 1
if XOrm.Read(user) { // 精确查找,检查缓存标记。
	fmt.Printf("User: %v\n", user.Name)
}

// 条件读取:支持模糊查找和条件匹配。
cond := XOrm.Cond("age > {0}", 18)
if XOrm.Read(user, cond) { // 模糊查找,可能触发远端读取。
	fmt.Printf("User: %v\n", user.Name)
}

// 删除操作:标记删除状态。
XOrm.Delete(user) // 通过事务缓冲至提交队列中删除。

// 清除操作:标记清除状态
cond = XOrm.Cond("age < {0}", 18)
XOrm.Clear(user, cond) // 通过事务缓冲至提交队列中清除。

// 列举操作:从缓存和远端组合数据。
var users []*User
cond = XOrm.Cond("age > {0} && name contains {1}", 18, "test")
XOrm.List(&users, cond) // 依次检查会话缓存、全局缓存、远端数据。

注意: 1. 所有操作必须在 Watch() 和 Defer() 之间进行 2. 写入操作会同时更新会话缓存和全局缓存 3. 读取操作遵循缓存优先级:会话缓存 > 全局缓存 > 远端数据 4. 删除和清除操作仅做标记,实际删除在会话提交时执行 5. 列举操作可能会同时访问缓存和远端数据

3.2 指标监控

支持 Prometheus 指标监控,可以实时监控 CRUD 提交的性能和资源使用情况:

指标说明:

| 指标 | 类型 | 描述 |
|------|------|------|
| xorm_commit_queue | Gauge | 所有队列中等待提交的对象总数 |
| xorm_commit_total | Counter | 所有队列已经提交的对象总数 |
| xorm_commit_queue_{n} | Gauge | 第 n 个队列中等待提交的对象数量 |
| xorm_commit_total_{n} | Counter | 第 n 个队列已经提交的对象总数 |

3.3 可选配置

支持通过首选项配置对提交队列进行调整:

配置参数:

  • Orm/Commit/Queue:提交队列的数量,默认为 CPU 核心数,-1 表示禁用提交队列
  • Orm/Commit/Queue/Capacity:单个队列的容量,默认为 100000

配置示例:

{
    "Orm/Commit/Queue": 8,
    "Orm/Commit/Queue/Capacity": 100000
}

更多信息请参考模块文档。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Clear

func Clear[T IModel](model T, cond ...*Condition)

Clear 根据条件批量标记数据模型为清除状态。 model 为要清除的数据模型,必须实现 IModel 接口。 cond 为可选的查询条件列表,用于匹配要清除的数据。

清除操作首先验证模型是否已注册,然后创建标记映射用于跟踪已处理的对象。 在会话内存清除阶段,遍历会话内存中的对象,对匹配条件的对象设置删除标记,并记录到标记映射中。 如果启用了缓存,在全局内存清除阶段,遍历全局内存中的对象,对匹配条件的对象设置删除标记。 对于未在会话内存中处理过的对象,会克隆到会话内存并设置相应的删除标记。

需要注意的是,清除操作是软删除,不会立即从内存中移除数据,被标记清除的数据在读取时会被忽略。 该函数是线程不安全的,操作相同的数据模型时,需要控制并发或使用适当的同步方式(如:Mutex)以确保操作的正确性。

func Close

func Close()

Close 关闭所有的提交队列并等待所有未完成的批次处理完成。 此函数会发送退出信号并等待所有队列完成当前工作。

func Defer

func Defer()

Defer 结束 CRUD 操作监控。 函数获取当前 goroutine ID 并检索对应的上下文实例。 如果是读写操作,会自动对比 CRUD 前后的数据变更(新建、删除和修改等)。 然后对变更进行合批并路由到(基于 goroutine ID)指定的队列中进行异步提交。 对于只读操作,仅清理会话映射,不进行数据同步。

此函数应通过 defer 调用,确保每个 Watch 都有对应的 Defer。

func Delete

func Delete[T IModel](model T)

Delete 标记数据模型为删除状态。 model 为要删除的数据模型,必须实现 IModel 接口。

删除操作首先验证模型是否已注册。如果启用了缓存,会在全局内存中查找对应的对象, 如果存在,则设置其删除标记为 true。 然后在会话内存中创建或获取会话对象,并设置删除标记为 true。

需要注意的是,删除操作是软删除,不会立即从内存中移除数据,被标记删除的数据在读取时会被忽略。 该函数是线程不安全的,操作相同的数据模型时,需要控制并发或使用适当的同步方式(如:Mutex)以确保操作的正确性。

func Dump

func Dump(models ...IModel)

Dump 清除数据模型的缓存数据。 models 为要清除的数据模型,若未指定则清除所有模型的缓存。

func Flush

func Flush(gid ...int64)

Flush 将等待指定的队列提交完成。 gid 参数为 goroutine ID,若未指定,则使用当前 goroutine ID, 若 gid 为 -1,则表示等待所有的队列提交完成。

func Incre

func Incre(model IModel, columnAndDelta ...any) int

Incre 获取并自增指定列的最大值。model 参数为要操作的数据模型,必须实现 IModel 接口。 columnAndDelta 为可变参数,支持多种组合:无参数时自增主键且增量为 1;一个参数时,若为字符串则 指定列名且增量为 1,若为整数则使用主键并指定增量;两个参数时,第一个为列名(字符串),第二个为增量(整数)。

函数首先获取或创建模型的最大值缓存,然后解析参数确定目标列名和增量值。如果未指定列名,会尝试使用主键列,若无主键则报错。 获取当前最大值时优先使用缓存的值,如果缓存不存在,则从远端数据获取,最后计算并缓存新值。 函数返回自增后的新值,如果列名为空,则返回 0。

需要注意的是,缓存的最大值在程序重启后会重置。 该函数是线程安全的,可以确保单实例内的数据唯一性。

func List

func List[T IModel](model T, writableAndCond ...any) []T

List 获取数据模型的列表。model 参数为要查询的数据模型,必须实现 IModel 接口。 writableAndCond 为可变参数,可包含布尔值(表示是否可写)和查询条件对象(*Condition 类型)。

函数首先验证模型是否已注册,然后解析参数获取可写标记和查询条件。查询数据时按照优先级依次从会话内存、全局内存和远端数据获取。 会话内存查询会过滤掉已标记删除的数据并应用查询条件; 全局内存查询会克隆数据到会话内存并处理覆盖数据; 远端数据查询会将数据同步到全局内存(如果启用缓存)和会话内存,并处理删除标记以确保数据一致性。 对于远端查询结果,函数会检查并使用会话内存和全局内存中的最新数据,移除被标记删除的数据,并添加仅在会话内存或全局内存中的匹配数据作为补充同步。 函数返回满足条件的数据模型切片,已被标记删除的数据将被过滤。

需要注意的是,返回的数据是原始数据的克隆,非条件列举可能导致数据不同步,建议避免在异步操作期间进行条件列举。 该函数是线程安全的,可以确保单实例内的数据一致性。

func Meta added in v0.0.2

func Meta(model IModel, cache bool, writable bool)

Meta 注册一个模型。 model 为模型实例。 cache 指定是否缓存。 writable 指定是否可写。 如果模型为 nil 或已注册,将触发 panic。

func Print added in v0.0.2

func Print() string

Print 生成缓存的文本信息。 返回包含以下信息的字符串:

[Data]: 缓存数据
[List]: 列举状态
[Incre]: 自增记录
[Lock]: 数据锁状态

func Read

func Read[T IModel](model T, writableAndCond ...any) T

Read 从数据源读取数据模型。model 参数为要读取的数据模型,必须实现 IModel 接口。 writableAndCond 为可变参数,可包含布尔值(表示是否可写)和查询条件对象(*Condition 类型)。

函数根据是否有查询条件采用不同的读取策略。对于精确查找(无查询条件),首先尝试从会话内存中读取, 如果启用缓存则尝试从全局内存中读取,最后从远端数据读取。对于模糊查找(有查询条件), 仅缓存模式下先查询会话内存再查询全局内存;其他模式则按照会话列表、全局列表、远端数据的顺序查找。

函数返回读取到的数据模型,如果数据被标记为删除,模型的 IsValid 将被设置为 false。

该函数是线程安全的,可以确保单实例内的数据一致性。

func Watch

func Watch(writable ...bool) int

Watch 开始 CRUD 操作监控。 writable 是可选的,默认为 true(读写模式),设置为 false 则为只读模式。 函数获取当前 goroutine ID,生成新的会话 ID,从对象池获取上下文实例并初始化(记录开始时间和设置读写模式)。 并返回新分配的会话 ID。

使用示例:

sid := Watch()        // 开始 CRUD 监控。
defer Defer()         // 结束 CRUD 监控。

func Write

func Write[T IModel](model T)

Write 将数据模型写入到内存缓存中。model 参数为要写入的数据模型,必须实现 IModel 接口。

函数首先验证模型是否已注册,然后设置模型为有效状态。 如果启用了缓存,会克隆模型并写入全局内存,同时清除删除标记。 接着写入会话内存,设置创建标记,并清除删除标记和清理标记。

需要注意的是,写入操作不会立即持久化到远端数据。 该函数是线程不安全的,操作相同的数据模型时,需要控制并发或使用适当的同步方式(如:Mutex)以确保操作的正确性。

Types

type Condition

type Condition struct {
	Base   *orm.Condition // 基础条件
	Limit  int            // 分页限定
	Offset int            // 分页偏移
	// contains filtered or unexported fields
}

Condition 表示一个查询条件,包含基础条件和分页信息。

func Cond added in v0.0.2

func Cond(condOrExprAndParams ...any) *Condition

Cond 创建新的条件。

用法: 1. Cond() - 创建空条件 2. Cond(existingCond *orm.Cond) - 从现有条件创建 3. Cond("a > {0} && b == {1}", 1, 2) - 从表达式和参数创建

func (*Condition) Ctor added in v0.0.2

func (c *Condition) Ctor(obj any)

Ctor 初始化条件。

type IModel

type IModel interface {
	// Ctor 执行模型的构造初始化。
	// obj 为模型实例,必须是实现了 IModel 接口的结构体指针。
	// 此方法会在模型创建时自动调用,用于初始化模型的基本状态。
	Ctor(obj any)

	// OnEncode 在对象编码前调用。
	// 子类可以重写此方法以实现自定义的编码逻辑。
	// 通常用于在数据写入前对字段进行预处理。
	OnEncode()

	// OnDecode 在对象解码后调用。
	// 子类可以重写此方法以实现自定义的解码逻辑。
	// 通常用于在数据读取后对字段进行后处理。
	OnDecode()

	// OnQuery 在执行查询时调用。
	// 子类可以重写此方法以实现自定义的查询逻辑。
	// 通常用于在执行查询前追加一个全局的条件,如数据分区等。
	// action 是查询的类型,包括:Count、Max、Min、Read、List、Delete、Clear。
	// cond 是查询的条件,传入的值可能为空。
	// 返回执行查询的最终条件。
	OnQuery(action string, cond *orm.Condition) *orm.Condition

	// AliasName 返回数据库别名。
	// 返回值用于标识不同的数据库连接。
	// 此方法必须由子类实现。
	AliasName() string

	// TableName 返回数据表名称。
	// 返回值用于标识数据库中的具体表。
	// 此方法必须由子类实现。
	TableName() string

	// ModelUnique 返回模型的唯一标识。
	// 返回值格式为 "数据库别名_表名"。
	// 用于在缓存和其他场景中唯一标识一个模型类型。
	ModelUnique() string

	// DataUnique 返回数据记录的唯一标识。
	// 返回值格式为 "模型标识_主键值"。
	// 用于在缓存和其他场景中唯一标识一条记录。
	DataUnique() string

	// DataValue 获取指定字段的值。
	// field 为字段名称。
	// 返回字段值,若字段不存在则返回 nil。
	DataValue(field string) any

	// Count 统计符合条件的记录数量。
	// cond 为可选的查询条件。
	// 返回记录数量,如果发生错误则返回 -1。
	Count(cond ...*Condition) int

	// Max 获取指定列的最大值。
	// column 为可选的列名,若不指定则使用主键列。
	// 返回最大值,如果发生错误则返回 -1。
	Max(column ...string) int

	// Min 获取指定列的最小值。
	// column 为可选的列名,若不指定则使用主键列。
	// 返回最小值,如果发生错误则返回 -1。
	Min(column ...string) int

	// Write 写入或更新当前记录。
	// 在写入前会调用 OnEncode 进行编码处理。
	// 返回受影响的行数,如果发生错误则返回 -1。
	Write() int

	// Read 读取符合条件的记录。
	// cond 为可选的查询条件,若不指定则使用主键作为查询条件。
	// 读取成功后会调用 OnDecode 进行解码处理。
	// 返回是否成功读取到记录。
	Read(cond ...*Condition) bool

	// List 查询符合条件的记录列表。
	// rets 必须是指向切片的指针,用于存储查询结果。
	// cond 为可选的查询条件,可以指定偏移量和限制数量。
	// 返回查询到的记录数量,如果发生错误则返回 -1。
	List(rets any, cond ...*Condition) int

	// Delete 删除当前记录。
	// 使用主键作为删除条件。
	// 返回受影响的行数,如果发生错误则返回 -1。
	Delete() int

	// Clear 清理符合条件的记录。
	// cond 为可选的查询条件,若不指定则清理所有记录。
	// 返回受影响的行数,如果发生错误则返回 -1。
	// 注意:MySQL Connector 最大的参数是 65535,清理大量数据时可能会触发错误:Prepared statement contains too many placeholders,解决方法为分批执行清理。
	Clear(cond ...*Condition) int

	// IsValid 检查或设置对象的有效性。
	// value 为可选的设置值,如果提供则设置对象的有效性状态。
	// 返回对象当前的有效性状态。
	IsValid(value ...bool) bool

	// Clone 创建对象的深度拷贝。
	// 拷贝后会调用 OnDecode 进行解码处理。
	// 返回新的对象实例,如果拷贝失败则返回 nil。
	Clone() IModel

	// Json 将对象转换为 JSON 字符串。
	// 返回 JSON 格式的字符串表示。
	Json() string

	// Equals 比较两个对象是否相等。
	// model 为待比较的对象。
	// 返回两个对象的所有数据库字段是否完全相等。
	Equals(model IModel) bool

	// Matchs 检查对象是否匹配指定条件。
	// cond 为可选的匹配条件。
	// 返回对象是否满足所有条件。
	Matchs(cond ...*Condition) bool
}

IModel 定义了数据模型的基础接口。 实现此接口的类型可以参与数据库的 CRUD 操作和缓存管理。

type Model

type Model[T any] struct {
	// contains filtered or unexported fields
}

Model 实现了 IModel 接口的基础模型。 T 为具体的模型类型,必须是结构体类型。 所有的具体模型类型都应该嵌入此类型。

func (*Model[T]) AliasName

func (md *Model[T]) AliasName() string

AliasName 返回数据库别名。 此方法需要被子类重写,默认会触发 panic。

func (*Model[T]) Clear

func (md *Model[T]) Clear(cond ...*Condition) int

Clear 清理符合条件的记录。 cond 为可选的查询条件,若不指定则清理所有记录。 返回受影响的行数,如果发生错误则返回 -1。 注意:MySQL Connector 最大的参数是 65535,清理大量数据时可能会触发错误:Prepared statement contains too many placeholders,解决方法为分批执行清理。

func (*Model[T]) Clone

func (md *Model[T]) Clone() IModel

Clone 创建对象的深度拷贝。 拷贝后会调用 OnDecode 进行解码处理。 返回新的对象实例,如果拷贝失败则返回 nil。

func (*Model[T]) Count

func (md *Model[T]) Count(cond ...*Condition) int

Count 统计符合条件的记录数量。 cond 为可选的查询条件。 返回记录数量,如果发生错误则返回 -1。

func (*Model[T]) Ctor

func (md *Model[T]) Ctor(obj any)

Ctor 初始化模型实例。 obj 必须实现 IModel 接口。 此方法会在模型创建时自动调用。

func (*Model[T]) DataUnique

func (md *Model[T]) DataUnique() string

DataUnique 返回数据记录的唯一标识。 返回值格式为 "模型标识_主键值"。 如果模型信息或主键未找到,将返回空字符串。

func (*Model[T]) DataValue

func (md *Model[T]) DataValue(field string) any

DataValue 获取指定字段的值。 field 为字段名称。 返回字段值,若字段不存在则返回 nil。

func (*Model[T]) Delete

func (md *Model[T]) Delete() int

Delete 删除当前记录。 使用主键作为删除条件。 返回受影响的行数,如果发生错误则返回 -1。

func (*Model[T]) Equals

func (md *Model[T]) Equals(model IModel) bool

Equals 比较两个对象是否相等。 model 为待比较的对象。 返回两个对象的所有数据库字段是否完全相等。

func (*Model[T]) IsValid

func (md *Model[T]) IsValid(value ...bool) bool

IsValid 检查或设置对象的有效性。 value 为可选的设置值。 返回对象是否有效。

func (*Model[T]) Json

func (md *Model[T]) Json() string

Json 将对象转换为 JSON 字符串。 返回 JSON 格式的字符串表示。

func (*Model[T]) List

func (md *Model[T]) List(rets any, cond ...*Condition) int

List 查询符合条件的记录列表。 rets 必须是指向切片的指针,用于存储查询结果。 cond 为可选的查询条件,可以指定偏移量和限制数量。 返回查询到的记录数量,如果发生错误则返回 -1。

func (*Model[T]) Matchs

func (md *Model[T]) Matchs(cond ...*Condition) bool

Matchs 检查对象是否匹配指定条件。 cond 为可选的匹配条件。 返回对象是否满足所有条件。

func (*Model[T]) Max

func (md *Model[T]) Max(column ...string) int

Max 获取指定列的最大值。 column 为可选的列名,若不指定则使用主键列。 返回最大值,如果发生错误则返回 -1。

func (*Model[T]) Min

func (md *Model[T]) Min(column ...string) int

Min 获取指定列的最小值。 column 为可选的列名,若不指定则使用主键列。 返回最小值,如果发生错误则返回 -1。

func (*Model[T]) ModelUnique

func (md *Model[T]) ModelUnique() string

ModelUnique 返回模型的唯一标识。 返回值格式为 "数据库别名_表名"。

func (*Model[T]) OnDecode

func (md *Model[T]) OnDecode()

OnDecode 在对象解码后调用。 子类可以重写此方法以实现自定义的解码逻辑。 通常用于在数据读取后对字段进行后处理。

func (*Model[T]) OnEncode

func (md *Model[T]) OnEncode()

OnEncode 在对象编码前调用。 子类可以重写此方法以实现自定义的编码逻辑。 通常用于在数据写入前对字段进行预处理。

func (*Model[T]) OnQuery added in v0.0.8

func (md *Model[T]) OnQuery(action string, cond *orm.Condition) *orm.Condition

OnQuery 在执行查询时调用。 子类可以重写此方法以实现自定义的查询逻辑。 通常用于在执行查询前追加一个全局的条件,如数据分区等。 action 是查询的类型,包括:Count、Max、Min、Read、List、Delete、Clear。 cond 是查询的条件,传入的值可能为空。 返回执行查询的最终条件。

func (*Model[T]) Read

func (md *Model[T]) Read(cond ...*Condition) bool

Read 读取符合条件的记录。 cond 为可选的查询条件,若不指定则使用主键作为查询条件。 读取成功后会调用 OnDecode 进行解码处理。 返回是否成功读取到记录。

func (*Model[T]) TableName

func (md *Model[T]) TableName() string

TableName 返回数据表名称。 此方法需要被子类重写,默认会触发 panic。

func (*Model[T]) Write

func (md *Model[T]) Write() int

Write 写入或更新当前记录。 在写入前会调用 OnEncode 进行编码处理。 返回受影响的行数,如果发生错误则返回 -1。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL