13. ORM Part 2: 定义对象¶
游戏工程师在SourceTree的 src/object_model/
目录下使用JSON文件定义对象。
这时指定对象名和属性方式如下。
{
"ObjectName": {
"AttributeName": "Type Flags",
"AttributeName": "Type Flags",
...
},
"ObjectName": {
"AttributeName": "Type Flags",
"AttributeName": "Type Flags",
...
},
...
}
在这儿的 ObjectName
会成为 Character 或者 Weapon 等 模型的名称。
并且,AttributeName
会成像 Title 或者 Level 一样属性的名称。
Important
Object, Attribute 的名称尽量输入为 Camel 的形式。
要不然,自动产生的Class或者Method名称不会漂亮。
(不好的例子)输入 my_character 的时候自动产生的参数名称:
Getmy_character()
(不好的例子)输入 myCharacter 自动产生的参数名称:
GetmyCharacter()
(好的例子)输入 MyCharacter 自动产生的参数名称:
GetMyCharacter()
Tip
使用JSON的时候不能使用 // ...
或者 /* ... */
形式的注释, iFun Engine的ORM定义文件可使用这样的注释。
开发阶段中,这样方式在模型或者档案上留标注的时候会有用。
13.1. Attribute 的 Type¶
Attribute的类型的话,iFun Engine提供的基本类型或者其他模型名称都可以使用,并且Array或者Map形式也可以使用。
13.1.1. 基本类型¶
Bool
: 意味着真/假。Integer
: 意味着整数。Double
: 意味着实数。String(n)
: 意味着n个字符串。Important
String(n) 的话不是Byte单位,而是数国际码单位。 有需要的话,可以使用 util::GetUtf8Length() 确认字符单位数。
如果保存n字符以上字符串的话,切断n字符以后部分后保存。 如果需要切断明确的特定字符以下的话,使用 util::TruncateUtf8() 参数即可。
Important
String
不再支持,一定使用String(n)
。如果已有的项目中使用
String
的话,因为String
和String(n)
不能并用,所以需要要么继续使用String
要么之前使用的东西换成String(n)
。
// 14个文字, 36 Byte字符串
std::string s = "松鼠像坐旧筛筐";
BOOST_ASSERT(14 == util::GetUtf8Length(s));
BOOST_ASSERT(36 == s.size());
// 切断从头起三个字
std::string t = util::TruncateUtf8(s, 3);
BOOST_ASSERT("松鼠" == t);
13.1.2. 对象类型¶
除了基本类型之外,还可以把其他模型的名称使用为类型。这情况下该属性有了对象类型。 不需要一定在前边宣布该模型。
下面例子中 MyChracter 属性成为 Chracter 的对象类型。
"User": {
"MyCharacter": "Chracter"
},
"Character": {
"Hp": "Integer",
"Mp": "Integer"
}
13.1.3. 数组 (Array)¶
类型后面添加 []
的话成为数组形式。
举个例子 Integer[]
, String(12)[]
, Character[]
意味着基本类型的各个整数数组,长为12个的字符串数组,而且使用者指定的 Character 的类型。
数组类型的属性产生C++/C#类的时候也支持像 InsertAt()
或者 EraseAt()
一样使用索引的数组工作。
Important
数组时候中间删除已有的内容或者添加的话,因数组在整列而速度会变慢。 具体内容请您参考 Using Array and Map 。
13.1.4. 地图 (Map)¶
指定为 <KeyType, ValueType>
的形式。
在 KeyType
只能用基本类型, 在 ValueType
不仅用基本类型还可以用对象类型。
举个例子,<Integer, String(4)>
意味着以整数为Key和4个字符串为Value的地图类型,<String(64), Item>
意味着64个字符串为Key和Item为Value的地图类型。
13.2. Attribute 的 Flag¶
13.2.1. Key¶
该属性做成key。 Key不许重复值,一旦决定值,不会变更。 使用Key可以调用 Object。 在MySQL上设置为 Non-Clustered Index 以及 Unique Constraint 。
下面的例子是 Character 的 Name 指定为 Key的情况。
"Character": { "Name": "String Key" }
13.2.2. 복합키(Composite Key)¶
여러 속성을 하나의 복합키(Composite Key)로 지정합니다. 복합키는 키와 동일한 특징을 가지고 있으며 두 개 이상의 속성을 키로 등록할 때 사용할 수 있습니다.
Important
한 오브젝트에 복합키와 키를 동시에 사용할 수 없습니다.
아래 예제는 Map 오브젝트의 X와 Y 속성을 복합키로 지정한 경우입니다.
"MAP": { "X": "String(10)", "Y": "String(10)", ... "COMPOSITE_KEY":[ "X", "Y" ] }
13.2.3. Foreign¶
属性的类型使用为其他模型的名称的时候,可以指定 Foreign
。 这样方式从数据库加载队形的时候,没有自动加载该属性的对象,而是只加载对象的ID值后需要的时候才加载该属性的对象。
举个例子, 假设有下面的 Character 和 Weapon 模型
"Character": { "MyWeapon": "Weapon" }, "Weapon": { "Durability: "Integer" }
这种情况,从数据库加载 Character 的话,把 Weapon 类型的 MyWeapon 也一起加载.
有明确的所有关系的话这样自动加载方式很方便。 但是,共有的对象和属于别人的对象的话这样自动加载方式有可能会出现问题。 这时,可以指定 Foreign
这意味着 参考 。
"Character": { "MyWeapon": "Weapon Foreign" }, "Weapon": { "Durability: "Integer" }
如上指定 Foreign
的话,虽然加载 Character 但是,不自动地加载 MyWeapon 。 ㅇ但是,先保存 MyWeapon 的对象ID后, 从数据库加载 MyWeapon 的时候会使用。
Tip
在数组或者地图的情况下像 Item[] Foreign
或者 <Integer, Item> Foreign
一样数组和地图定义后面写 Foreign
。
13.3. 模型定义例子¶
下面的例子定义 Character 和 Item 的对象。 以后,本章和跟ORM相关的章都定义对象模型。
src/object_model/example.json
{
"User": {
"Id": "String(16) KEY",
"MyCharacter": "Character"
},
"Character": {
"Name": "String(16) Key",
"Exp": "Integer",
"Level": "Integer",
"Hp": "Integer",
"Mp": "Integer",
"Inventory": "Item[]",
"QuickSlot": "<Integer, Item>",
"EquippedItem": "<String(9), Item>"
},
"Item": {
"Type": "String(16)"
}
}
约20行的渐变的Object Modeling工作,User, Character, Item 的对象都能实现。 那现在使用按照这JSON自动产生的Class的话, iFun Engine能自动处理像数据库处理,Cache实现,实现扩展处理,多线程处理等复杂的工作。