上篇提到快速开发平台需要自动处理从客户端界面对象到服务端内存对象之间的转换,再通过ORMapping转变为数据库记录。在这些数据的转化过程中不管形式上变化有多大,其结构永远是相同的,这些结构我们称之为元数据,一般采用XML来定义。如以下的XML是一个关于职员对象的元数据定义:
<Entity name="Employee" label="职员">
<property uid="sys_0" label="编号" name="id" type="long"/>
<property name="name" label="姓名" type="string" length="30" uid="id_1"/>
<property name="email" label="电子邮件" type="string" length="100" uid="id_2">
<property name="birthday" label="出生日期" type="timestamp" uid="id_7"/>
<property name="msn" label="MSN帐号" type="string" length="100" uid="id_8"/>
<property name="qq" label="QQ帐号" type="string" length="50" uid="id_9"/>
<property name="sex" label="性别" type="long" uid="id_10" systemProperty="true"/>
<property name="photo" label="照片" type="image" length="100" uid="id_11"/>
<property name="jobNo" label="工号" type="string" length="100" uid="id_13"/>
</Entity>
在这个元数据定义中,规定了职员对象的名称: Employee ,以及相关的属性,每一个属性也规定了名称、类型以及长度等必要的数据。
根据以上结构,在客户端中如果数据是用Javascript来表达,那么员工对象的JSON格式为:
{
id:1,
name:”张三”,
email:”zhangs@company.com”,
birthday:”1980-1-1”,
msn:””,
qq:””,
sex:1,
...
}
在服务端中的Java class可能是这样的:
public class Employee{
private long id;
private String name;
private String email;
...
public long getId(){
return id;
}
public void setId(long id){
this.id = id;
}
...
}
而数据库记录则为:
id | name | birthday | msn | ... | jobNo | |
1 | 张三 | zhangs@company.com | 1980-1-1 | 2001 |
快速开发平台要根据“职员”的元数据定义实现将Javascript对象通过http协议转移为相应的Java的Employee对象,再将Java对象永久化存储为数据库记录到Employee表中,反向也是如此。在这个过程中,快速开发平台要经历多道难关,首先一个就是要根据元数据生成相应的对象结构。对于Javascript对象来说要简单得多,因为我们可以对JS对象任意地添加或删除相关属性,所以完全可以根据元数据来生成对象结构;那么服务器中的Java class怎么办呢?为了实现与JS相同的功能,我们必须放弃一个元数据对应一个class的方式,而可以采用Map<String, Object>类型来表示对象数据,这样就可以根据元数据定义生成相应的Map对象了。如果是在人工编码过程中使用Map来表示业务对象,这绝对不是一个好的方法,因为程序员很难去确定在Map中需要存储什么键值,以及各健值的数据类型,但是我们别忘了,现在是由快速开发平台自动来处理这些问题,因此上述的情况完全可以忽略;将Map对象转换为数据库记录应该也不是太大的问题,最困难的是如何根据元数据生成相应的表结构?如果纯粹用JDBC来实现当然也是可以的,完全能够将元数据转换为特定数据库的DDL语句,通过执行DDL语句来创建相应的数据库表,但如能通过第三方库(如:Hibernate)来实现这个功能将会省事很多。
通过定义元数据我们实现了业务对象在应用系统各层中的自动数据转换,以及业务对象的永久化存储问题,这是任何一个快速开发平台的基础,没有这个基础,其他的任何功能都无从谈起。