🔢 数据库底层操作
没有数据库底层的操作?
在讲解的Entity一文中提到,只要属性的persistent标签设置为True,该属性就会自动保存进数据库中,同时在从数据库创建拥有该属性的Entity实体(通过API-KBEngine.createEntityFromDBID以及类似API)时,该属性会自动从数据库读取并设置。那不需要数据库底层的操作啦?引擎都帮我们做了什么?我们如果想对数据库底层进行操作,又是否可以呢?
一般在做服务器开发时,都会涉及到数据库连接、数据库ORM等专业知识,并且开发时会消耗大量人力和时间成本。
下面我们会围绕这几个问题来进行解释:
- 如何增加一个会永久保存(即持久化、自动存取数据库)的属性?
- 引擎都帮我们做了什么?
- 如果想对数据库底层进行操作,又是否可以呢?
如何增加一个会永久保存(即持久化、自动存取数据库)的属性?
很简单!在def配置中的Properties属性定义块中增加一个属性,并设置Persistent为True。拿之前在讲解Entity概念时的例子,Avatar实体下有一个name属性。如下:
<root>
<!--属性定义-->
<Properties>
<!--角色的名字-->
<name>
<!--unicode作为名字类型-->
<Type> UNICODE </Type>
<!--长度设置为20-->
<DatabaseLength> 20 </DatabaseLength>
<!--cell以及所有client都有该属性,并由cell向所有客户端同步他-->
<Flags> ALL_CLIENTS </Flags>
<Default> </Default>
<!--需要持久化保存-->
<Persistent> true </Persistent>
</name>
</Properties>
...
...
</root>
这样,我们在Avatar实体中就增加了一个名为name的属性,并且设置为持久化。这个属性就会被自动保存进数据库,并在从数据库创建拥有Avatar实体(通过API-KBEngine.createEntityFromDBID以及类似API)时,该属性会自动从数据库读取并设置。
引擎帮我们做了什么?
大家可能会疑问,这么方便,都不需要操作数据库了?但是我们这些喜欢钻研的开发者肯定想一探究竟,强大的KBE引擎到底帮我们做了什么?
概览:
我们先来看下数据库中自动生成了哪些表:

表的介绍在下面会进行阐述,我们先来看下大致分了两种表格:
前缀kbe的表是引擎内部机制所需要的表格,如图中kbe_serverlog表是服务器日志记录、kbe_entitylog表是实体相关记录等。
前缀tbl的表是根据开发者的实体、组件、自定义数据类型的配置而自动创建的表,如本例中的tbl_Avatar表是实体Avatar的记录表。
大家肯定还会疑问,其他的表看上去有一定的规则,他们都是什么?(这些表是在开发一个mmo demo时自动生成的,这要和该demo的业务有一定关系,这里不再赘述。不过该参考图有一定的教学意义哈。)
我们来看一下表名的取名规则吧:
表名的取名规则:
引擎内部机制的表会以关键字
kbe
为前缀,如图中的kbe_serverlog
、kbe_entitylog
等。前缀为关键字tbl的表是根据开发业务的配置自动创建的表。
以下划线_作为分隔符进行划分。
第一个名字是Entity实体的名称,如
tbl_Avatar
、tbl_Avatar_combat
、tbl_Avatar_skillBox
。自定义数据类型,由于它需要自己独特的存储结构,所以会新建一个表进行记录。其命名按照
所属实体名_所在属性名{_数据结构内的属性名}
进行设置,{}
内是可选,根据该自定义数据类型配置时的Properties块。(参见自定义数据类型一节)
相关信息
如我们例子中:tbl_Account_characters_values
,Account实体的def配置如下:
<Properties>
<!--角色的字典-->
<characters>
<Type> AVATAR_INFO_LIST </Type>
<Flags> BASE </Flags>
<Default> </Default>
<Persistent> true </Persistent>
</characters>
</Properties>
其中,表名中的characters与属性characters对应,Type=AVATAR_INFO_LIST
是一个自定义数据类型,我们再来看下AVATAR_INFO_LIST
的申明(在{项目资产库}/scripts/entity_defs/types.xml
中):
<!-- AVATAR信息列表 -->
<AVATAR_INFO_LIST> FIXED_DICT
<implementedBy>AVATAR_INFO.avatar_info_list_inst</implementedBy>
<Properties>
<values>
<Type> ARRAY <of> AVATAR_INFO </of> </Type>
</values>
</Properties>
</AVATAR_INFO_LIST>
其中,表名中的values与该配置中的values对应。这样大家都了解了吧。
组件名紧跟实体名之后,如Avatar拥有一个skillBox组件,则名字为tbl_Avatar_skillBox。(组件的知识请参见组件的概念一节)
组件内的持久化属性,紧跟组件名之后。如Avatar的skillBox组件下有持久化属性skills,则名字为tbl_Avatar_skillBox_skills。
SkillBox.def配置如下:
<!-- SkillBox.def中 -->
<Properties>
<skills>
<Type> ARRAY <of> SKILLID </of> </Type>
<Flags> CELL_PRIVATE </Flags>
<Persistent>true </Persistent>
</skills>
</Properties>
表结构:
还记得我们例子中,我们的Avatar实体有一个name属性吗?先来看下tbl_Avatar的表结构,如图:

内置的列:
sm_autoLoad
: 该实体是否自动加载。
sm_x_position
: 该实体保存的位置,在引擎中position是实体默认拥有的属性。
sm_x_direction
: 该实体保存的方向,在引擎中direction是实体默认拥有的属性。
自定义的列:
sm_name
: 这就是我们定义的属性name的字段!
其他的列,是demo中的业务所需,这里不再赘述。我们来看下字段设计图:

引擎把属性name
的配置,都自动匹配到数据库中的不同设计。如:类型UNICODE
对应了varchar
的数据库字段类型,DatabaseLength
对应数据库中的字段长度,Default
对应了数据库字段的默认值等。
这样一来,我们的开发可以节省非常多的时间,同时也能节省可观的人力成本。不用关心数据库底层的东西,我们开发者只要关心上层的业务设计就好!
那么问题就来了,对于有特殊需求或者对数据库开发有深厚经验的开发人员,想要运用一些底层的技术去直接操作数据库,可不可以呢?答案是:可以!
如何对数据库底层进行操作
如果开发者还是有需求对数据库底层进行操作,引擎提供了对应的工具和API:KBEngine.executeRawDatabaseCommand
,以及可以使用Python第三方库pymysql
或pyredis
。
引擎内置的API操作数据库底层
这个脚本函数在数据库上执行原始数据库命令,该命令将直接由相关数据库进行解析。 该API提供4个参数,分别为:
command
: 交给数据库执行的指令。这个数据库命令将会因为不同数据库配置方案而不同。对于方案为MySQL数据库它是一个SQL查询语句。
callback
: 可选参数,带有命令执行结果的回调对象(比如说是一个函数)。这个回调带有4个参数:
提示
result
:结果集合。这个结果集合参数是一个行列表。 每一行是一个包含字段值的字符串列表。命令执行没有返回结果集合(比如说是DELETE命令), 或者 命令执行有错误时这个结果集合为None。rows
:int,影响的行数。表示命令执行受影响的行数。insertid
:自増长值,类似于实体的databaseID,当成功的向一张带有自増长类型字段的表中插入数据时,它返回该数据在插入时自増长字段所被赋于的值。error
:错误信息,当命令执行有错误时,这个参数是一个描述错误的字符串。命令执行没有发生错误时这个参数为None。
threadID
: int32,可选参数,指定一个线程来处理本条命令。用户可以通过这个参数控制某一类命令的执行先后顺序(dbmgr是多线程处理的),默认是不指定,如果threadID是实体的ID, 那么将加入到该实体的存档队列中由线程逐条写入。
dbInterfaceName
: string,可选参数,指定由某个数据库接口来完成, 默认使用”default”接口。详情参见引擎配置kbengine.xml中dbmgr->dabaseInterfaces定义。
注意
使用该函数修改实体数据可能不生效,因为如果实体已经检出,被修改过的实体数据将仍会被实体存档而导致覆盖。强烈不推荐这个函数用于读取或修改实体数据。
Python第三方库操作数据库底层
这里推荐pymysql、pyredis,具体参考它们的官网资料。
PythonMySQL: https://pypi.python.org/pypi/PyMySQL
PythonRedis: https://pypi.python.org/pypi/redis