orm

ormentry.lua

单条数据条目对象。

常用方法

  • M:get(filed_name)
    函数作用域:M:new 对象的成员函数
    函数名称:get
    描述: 获得对象指定字段的值
    参数:
    - filed_name (string): 字段名
    返回值:

    1. value(number or string): 值
  • M:set(filed_name, filed_value)
    函数作用域:M:new 对象的成员函数
    函数名称:set
    描述: 修改条目数据的值
    参数:
    - filed_name (string): 字段名
    - filed_value (number or string): 字段值
    返回值:

  • M:get_entry_data()
    函数作用域:M:new 对象的成员函数
    函数名称:get_entry_data
    描述: 获取所有数据
    参数:

    返回值:

    1. value_map(table):数据表

使用中通常不需要调用

  • M:new(filed_name)
    通常只在ormtable.lua中调用,外部不需要调用。
    函数作用域:M 对象的成员函数
    函数名称:new
    描述: 新建条目数据对象
    参数:
    - ormtab (table): ormtable对象
    - entry_data(table): 数据表
    返回值:

    1. entry(table): entry对象
  • M:get_change_map()
    通常只在ormtable.lua中调用,外部不需要调用。
    函数作用域:M:new 对象的成员函数
    函数名称:get_change_map
    描述: 获取修改条目
    参数:

    返回值:

    1. change_map(table):修改数据表
  • M:clear_change()
    通常只在ormtable.lua中调用,外部不需要调用。
    函数作用域:M:new 对象的成员函数
    函数名称:clear_change
    描述: 清除变更标记
    参数:

    返回值:

ormtable.lua

这是orm的核心实现,通常我们创建一个表,通过它来定义。

构建前调用

  • M:new(tab_name)
    通常只在ormtable.lua中调用,外部不需要调用。
    函数作用域:M 对象的成员函数
    函数名称:new
    描述: 新建表对象
    参数:
    - tab_name (string): 对应数据库的表名
    返回值:
    1. orm_obj(table): 表对象

定义字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local FILED_TYPE = {
int8 = 1,
int16 = 2,
int32 = 3,
int64 = 4,

uint8 = 11,
uint16 = 12,
uint32 = 13,

string32 = 31,
string64 = 32,
string128 = 33,
string256 = 34,
string512 = 35,
string1024 = 36,
string2048 = 37,
string4096 = 38,
string8192 = 39,

text = 51,
blob = 52,
}
  • M:int8(filed_name)
    函数作用域:M:new 对象的成员函数
    函数名称:int8
    描述: 定义一个int8类型的字段
    参数:
    filed_name(string): 字段名
    返回值:
    1. orm_obj(table): 表对象

返回值是一个orm_obj对象,我们可以链式定义。

1
2
3
4
5
local orm_obj = ormtable:new("user")
:string256("name")
:int8("sex")
:set_keys("name")
:builder(adapter) --adapter是对接的对应数据库
  • M:set_keys(filed_name)
    函数作用域:M:new 对象的成员函数
    函数名称:set_keys
    描述: 设置主键
    参数:
    …(string): 字段名列表。
    返回值:

    1. orm_obj(table): 表对象
  • M:set_cache(expire, inval, cache_limit)
    函数作用域:M:new 对象的成员函数
    函数名称:set_cache
    描述: 设置缓存时间
    参数:
    expire(number): 缓存时间。(创建和查询到entry会刷新缓存时间)
    inval(number): 自动保存时间间隔 (间隔一定时间,保存所有有修改的条目)
    cache_limit(number): 缓存总量限制,超出使用TTI淘汰策略
    返回值:

    1. orm_obj(table): 表对象
  • M:builder(adapterinterface)
    函数作用域:M:new 对象的成员函数
    函数名称:builder
    描述: 构建
    参数:
    adapterinterface(number): 数据库适配器
    返回值:

    1. orm_obj(table): 表对象

构建后调用

  • M:create_entry(entry_data_list)
    函数作用域:M:new 对象的成员函数
    函数名称:create_entry
    描述: 批量创建新数据
    参数:
    entry_data_list(table): 数据表列表
    返回值:
    1. entry_list(table or false): entry对象列表(创建成功的idx是entry对象,失败的是false值)
      异常情况:
  1. 创建的数据有异常,比如int8类型出现了100000的数值或者干脆就是个”string”类型的值,此时会出现断言错误。
    tab_name[t_player] set invaild value filed_name[sex] value[100000] filed_type[1]

  2. 当中途数据库宕机,由于创建过程可能是分批执行的,所以宕机的情况并不会导致断言,而是和主键冲突一样返回false

  3. 一条执行语句都超过包长度限制, 这时候会出现断言错误

  4. 出现主键冲突, 由于是分批执行的,过程中可能有成功的,并不会断言,并且同一批中有一条冲突,就会全部插入失败,这是数据库插入语句机制决定的。

  • M:create_one_entry(entry_data_list)
    函数作用域:M:new 对象的成员函数
    函数名称:create_one_entry
    描述: 创建一条数据
    参数:
    entry_data(table): 数据表
    返回值:
    1. entry(table): 成功entry对象,失败断言

异常情况:

  1. 创建的数据有异常,断言。
  2. 数据库宕机,断言。
  3. 主键冲突,断言。

创建过程是先调用数据库创建接口,再创建entry对象。

  • M:get_entry(…)
    函数作用域:M:new 对象的成员函数
    函数名称:get_entry
    描述: 查询多条数据
    参数:
    …(string or number): 遵循最左原则,填入keys对应字段的值进行查询
    返回值:
    1. entry_list(table): entry对象列表

异常情况:

  1. 参数一个没有,断言,因为没有一个参数,是用于查询表所有数据的,查询所有数据应该显示的调用get_all_entry,这样可能避免因为一个传参问题导致非常严重的BUG。
  2. 数据库宕机,断言。
  • M:get_one_entry(…)
    函数作用域:M:new 对象的成员函数
    函数名称:get_one_entry
    描述: 查询单条数据
    参数:
    …(string or number): 与get_entry不同的是,必须把所有keys的值填入
    返回值:
    1. entry(table or nil): 存在返回entry对象,不存在nil值

异常情况:

  1. 参数不全,断言,查询单条数据,应该传入所有主键值。
  2. 数据库宕机,断言。
  • M:save_entry(entry_list)
    函数作用域:M:new 对象的成员函数
    函数名称:save_entry
    描述: 批量保存数据
    参数:
    entry_list(table): entry对象列表
    返回值:
    1. ret_list(table): 成功true,失败false

异常情况:

  1. 数据库宕机 不会断言,因为保存也是批量分配执行的,并且设置间隔保存的时候会自动重试,所以不能断言。
  • M:save_one_entry(entry)
    函数作用域:M:new 对象的成员函数
    函数名称:save_one_entry
    描述: 保存一条数据
    参数:
    entry(table): entry对象
    返回值:
    1. ret(bool): 成功返回true,失败断言

异常情况:

  1. 数据库宕机,断言。
  • M:delete_entry(…)
    函数作用域:M:new 对象的成员函数
    函数名称:delete_entry
    描述: 删除数据
    参数:
    …(number or string): 遵循最左原则,填入keys对应字段的值进行查询删除。
    返回值:
    1. ret(bool): 成功返回true,失败断言

异常情况:

  1. 参数一个没有,断言,因为没有一个参数,是用于删除表所有数据的,删除所有数据应该显示的调用delete_all_entry,这样可能避免因为一个传参问题导致非常严重的BUG。
  2. 数据库宕机,断言。
  • M:get_all_entry()
    函数作用域:M:new 对象的成员函数
    函数名称:get_all_entry
    描述: 查询所有数据
    参数:

    返回值:
    1. entry_list(table): entry对象列表

异常情况:

  1. 数据库宕机,断言。
  • M:delete_all_entry()
    函数作用域:M:new 对象的成员函数
    函数名称:delete_all_entry
    描述: 删除所有数据
    参数:

    返回值:
    1. ret(bool): 成功返回true

异常情况:

  1. 数据库宕机,断言。
  • M:save_change_now()
    函数作用域:M:new 对象的成员函数
    函数名称:save_change_now
    描述: 立即保存所有修改
    参数:

    返回值:

  • M:get_entry_by_data(entry_data)
    函数作用域:M:new 对象的成员函数
    函数名称:get_entry_by_data
    描述: 通过数据获得entry
    参数:
    entry_data(table) : 实例的数据
    返回值:
    1. entry(string):entry对象

  • M:is_inval_save(entry_data)
    函数作用域:M:new 对象的成员函数
    函数名称:is_inval_save
    描述: 是否启动了间隔保存
    参数:
    返回值:
    1. ret(bool):true or false

ormadapter_mysql.lua

mysql适配器。
业务开发中,我们只需要调用new来创建一个适配器传入ormtable的builder构建函数中。

  • M:new(db_name)
    函数作用域:M 对象的成员函数
    函数名称:new
    描述: 新建适配器对象
    参数:
    - db_name (string): 表存在的数据库名称。
    返回值:
    1. apter(table): 适配器对象。

业务层不直接访问的方法,都是通过orm_table间接访问。

  • M:builder(tab_name, filed_list, filed_map, key_list)
    函数作用域:M:new 对象的成员函数
    函数名称:builder
    描述: 构建表,不存在构建,存在更新。
    参数:
    tab_name(string)表名。
    filed_list(table)字段列表,按定义顺序。
    filed_map(table)字段名和字段类型的映射。
    key_list(table)主键字段名列表。
    返回值:
    1. apter(table): 适配器对象。

builder会在ormtable调用builder的时候调用。

  • M:create_entry(entry_data_list)
    函数作用域:M:new 对象的成员函数
    函数名称:create_entry
    描述: 批量创建表数据
    参数:
    entry_data_list(table)数据表内容列表,数据经过ormtable过滤处理,空值string类型会是空串,number类型会是0。
    返回值:
    1. res_list(table): 成功true,失败false。

  • M:create_one_entry(entry_data)
    函数作用域:M:new 对象的成员函数
    函数名称:create_one_entry
    描述: 创建一条数据
    参数:
    entry_data(table)数据表内容,数据经过ormtable过滤处理,空值string类型会是空串,number类型会是0。
    返回值:
    1. ret(bool): 成功true,失败断言

  • M:get_entry(keys_values)
    函数作用域:M:new 对象的成员函数
    函数名称:get_entry
    描述: 查询表数据
    参数:
    keys_values(table)最左原则,keys的值。
    返回值:
    1. entry_data_list(table): 成功数据表列表,失败断言

  • M:get_one_entry(keys_values)
    函数作用域:M:new 对象的成员函数
    函数名称:get_one_entry
    描述: 查询单条数据
    参数:
    keys_values(table)最左原则,keys的值。
    返回值:
    1. entry_data(table): 成功数据表,失败断言

  • M:save_entry(entry_data_list, change_map_list)
    函数作用域:M:new 对象的成员函数
    函数名称:save_entry
    描述: 保存表数据
    参数:
    entry_data_list(table)数据表列表。
    change_map_list(table)数据表变更记录。
    返回值:
    1. ret_list(table): 成功true 失败false。

  • M:save_one_entry(entry_data, change_map)
    函数作用域:M:new 对象的成员函数
    函数名称:save_one_entry
    描述: 保存一条数据
    参数:
    entry_data(table)数据表。
    change_map(table)变更列表。
    返回值:
    1. ret(bool): 成功true失败断言

  • M:delete_entry(key_values)
    函数作用域:M:new 对象的成员函数
    函数名称:delete_entry
    描述: 删除表数据
    参数:
    keys_values(table)最左原则,keys的值。
    返回值:
    1. ret(bool): 成功true失败断言

ormadapter_mongo.lua

mongo db多了以下两个方法,批量插入和批量更新的时候,设置一次执行的数量,mysql不用这样是因为mysql可以获取到网络包的长度限制,并且数据包的长度外部也能知道(sql的长度),但是mongo,外部获取不到网络包的长度,不确定一次能够执行多少,按照chatgpt的回复,mongo的包长度限制为16M,高版本为64M,想着预留这个接口,用户根据表的数量大小,自己预估单次数量即可,默认一次10条,在大多数情况下都不会超过16M。

1
2
3
4
5
6
7
8
9
10
11
12
13
--设置单次整合批量插入的数量
function M:set_batch_insert_num(num)
assert(num > 0)
self.batch_insert_num = num
return self
end

--设置单次整合批量更新的数量
function M:set_batch_update_num(num)
assert(num > 0)
self.batch_update_num = num
return self
end

其他接口函数的实现会返回值都是统一的,这也是为什么orm的可以无缝切换数据库的原因。

orm_table_m.lua
有多个服务需要使用orm的时候,我们需要使用代理访问,这时候我们只在orm_table_m.lua服务中去构建操作orm对象。

具体示例可以查看
orm
我们可以以这种方式自定义一些方法,比如玩家的道具item,我们必须原子性的加减,并且减少不能小于0,我们可能就需要定义这样的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function handle.add_item(player_id, item_id, num)
assert(num >= 0)
local entry = g_orm_obj:get_one_entry(player_id, item_id)
if not entry then
log.error("add_item not exist item_id ",player_id, item_id)
return
end

local count = entry:get('count')
count = count + num
entry:set('count', count)

--没有启动间隔时间自动保存就立即保存
if not g_orm_obj:is_inval_save() then
g_orm_obj:save_one_entry(entry)
end

return count
end

常用的处理函数

  • create_entry(entry_data_list)
    函数作用域:handle
    函数名称:create_entry
    描述: 批量创建数据
    参数:
    entry_data_list(table)数据表列表
    返回值:
    1. data_list(table): 二级 成功值为entry_data失败值为false

  • create_one_entry(entry_data)
    函数作用域:handle
    函数名称:create_one_entry
    描述: 创建单条数据
    参数:
    entry_data(table)数据表
    返回值:
    1. entry_data(bool): 成功entry_data失败断言

  • get_entry(…)
    函数作用域:handle
    函数名称:get_entry
    描述: 查询多条数据
    参数:
    …(string or number)遵循最左原则,填入keys对应字段的值进行查询
    返回值:
    1. data_list(table): 数据表列表

  • get_one_entry(…)
    函数作用域:handle
    函数名称:get_one_entry
    描述: 查询一条数据
    参数:
    …(string or number)遵循最左原则,填入keys对应字段的值进行查询
    返回值:
    1. entry_data(table): 数据表

  • change_save_entry(entry_data_list)
    函数作用域:handle
    函数名称:change_save_entry
    描述: 批量变更保存数据
    参数:
    entry_data_list(table)数据表列表
    返回值:
    1. ret_list(table): 二级 成功值为true失败值为false

  • change_save_one_entry(entry_data)
    函数作用域:handle
    函数名称:change_save_one_entry
    描述: 变更保存一条数据
    参数:
    entry_data(table)数据表
    返回值:
    1. ret(bool):成功值为true失败断言

  • delete_entry(…)
    函数作用域:handle
    函数名称:delete_entry
    描述: 删除数据
    参数:
    …(string or number)遵循最左原则,填入keys对应字段的值进行删除
    返回值:
    1. ret(bool): 成功值为true失败断言

  • get_all_entry()
    函数作用域:handle
    函数名称:get_all_entry
    描述: 查询所有数据
    参数:

    返回值:
    1. ret(bool): 成功值为true失败断言

  • delete_all_entry()
    函数作用域:handle
    函数名称:delete_all_entry
    描述: 删除所有数据
    参数:

    返回值:
    1. ret(bool): 成功值为true失败断言

  • save_change_now()
    函数作用域:handle
    函数名称:save_change_now
    描述: 立即保存所有修改
    参数:

    返回值:

orm_table_client.lua

访问代理,这个文件的实现,主要有两个目的

  1. 解决热更问题,热更之后需要访问新的orm_table_m服务。
  2. 调用便捷性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
orm_table_client:instance("player"):not_exist_create({player_id = 10001})

local client = orm_table_client:new("player")
local entry_data = client:get(10001)
log.info("get:",entry_data)

--批量创建数据
local entry_data_list = {
{player_id = 10001},
{player_id = 10002},
{player_id = 10003},
{player_id = 10003},
}

--主键冲突,创建失败
local res_list = client:create_entry(entry_data_list)
log.info("res_list:", res_list)

封装以后调用相当于调用本地方法一样,但是使用中,应该注意,这里存在rpc调用。


orm
https://huahua132.github.io/2024/01/28/skynet_fly_api/orm/
作者
huahua132
发布于
2024年1月28日
许可协议