2.技术要点
O/R Mapping
PD从8.0开始,就不断加强O/R Mapping,除了代码模型的生成以外,PD也生成O/R Mapping的定义,诸如生成EJB CMP组件。用户可以定义O/R Mapping来建立OOM与PDM之间的关系。
PD支持3种方式的O/R Mapping:
第一种是从类图转换成数据模型之后由PD自动建立连接(适用于自顶向下的设计过程);
第二种是从数据模型转换成类图之后由PD自动建立连接(适用于自下向上的设计过程);
第三种是建立类图和数据模型之后由用户手动建立(适用于同步设计或者是后期的修改)
建立过程:
第一种:选择类图,然后设计持久类(POJO),完毕之后,选择Tools->Generate Physical Data Model。在弹出的窗口中,选择Detail标签,选中O/R Mapping选项,即可。读者可以选择是更新现有的数据库还是新建数据库。
第二种:与第一种建立过程相似,只是换成在数据库模型中选择Generate Object-Oriented Model
第三种:用户必须首先建立DataSource,在左边WorkSpace树形目录下找到类文件,然后右击选择New\Data Source,在弹出的窗口的Models标签中选择 ,并选择想与之关联的数据库模型。在类模型中打开类属性(双击要建立O/R Mapping的类),选择Mapping选项卡,点击 按钮添加刚才建立的DataSource。然后点击 添加类映射的数据表,即建立完毕。
用户可以添加多张表,它表示一个类可能对应多张表的映射,Hibernate的映射则应该用Join属性来指明。
注:当用户建立了ClassSource,PD会根据类的属性和表的字段自动建立AttributeMapping,当然用户也可以在AttributeMapping属性页下对其映射进行修改。
大家知道,Hibernate的映射文件必须包含对表的表述(比如:column,property属性等等),在PD中,通过元模型中的Mapping可以轻易地获取对应的表信息。图4是GTL中用到的O/R Mapping元模型。
O/R Mapping架构图:

架构说明:
1) Association:
在Asoociation元模型中,可以通过Mappings来获取AssociationMapping(即用户在Mapping for下选择的DataSource),每个AssociationMapping都会有SourceClassifiers,它是AsoociationSource标签内的映射集合,如图5所示。SourceClassifiers集合中的元素,也就是数据模型中的Reference元模型,如图6所示。
由于PD可以在Association Mapping下添加数据模型中的其他Reference和Table,所以在做Hibernate代码生成时,采用了类型判断,以避免因类型不匹配而造成的错误。


☺实现代码(表映射):(注:附录部分将介绍部分GTL语法)
.

☺实现代码(referenceColumnHelper模版):

2) Class和Attribute
获取数据库模型的方法与Association类似,在O/R Mapping中,ClassMapping的SourceFeature等价于数据表; AttributeMapping的SourceFeature等价于数据表中的列信息。图7给出了在编写过程中使用到的数据库元模型的架构图。
☺实现代码(获取类对应的表信息)

说明:Mappings.First.ClassSources表明当前Data Source下的表集合
☺实现代码(获取Attribute对应的列信息)
例如:%AttributeMappings.First.SourceFeature.Code%
%AttributeMappings.First.SourceFeature%对应于图7的Column元模型。

Extended Attribute
Hibernate生成工具中对于映射文件,难免要遇到大量的选项让用户选择或者输入,这时,我们就可以利用PD提供的Extended Attribute来扩展模型的属性。对于UML模型,除了Dependency和Generalization,其余模型均有Extended Attribute来扩展。
设置Extended Attribute步骤:进入扩展模型编辑窗口,在Profile下选择一个元模型,然后右键选择Extended Attribute, PD已提供了多种默认的选项(加括号的),当然用户增加自己的Extended Attribute Type(在Profile下的shared目录上按右键选择Extended Attribute Type,然后在右边可以设置列项内容以及默认值等等。设置完之后读者就可以在模型的扩展属性中引用到自定义的类型),如图8所示。在GTL中,可以用%属性名%引用到当前用户的选择值,也可以用%模版名%引用到GTL模版(读者可以选择模版并按F12跳转)。

Check Model
考虑,由于基于UML建立的DomainModel,对于Hibernate语法来说,难免有一些语法上的错误,比如:在两个类之间建立Association,但对应的表之间却没有Reference,或者是有Reference却没有Joins下的Column,这时我们应该给出一个错误警告,提示用户检查。
以刚才提到的AssociationCheck为例,将介绍如何实现用户自定义的Check。
打开Hibernate扩展模型,选中Profile\Association,右击选中New\Custom Check。在右边,读者可以看到有四个选项卡,如图9所示。

Check Script: 用于检测模型,%Check%=true, 将不出现错误信息。
Autofix Script: 用于自动修复模型错误,%Fix%=false, 表示不修复该错误。当PD监测到错误时,用户可以在错误上右键选择Automatic Correction即可。对于自动修复的错误,会在图标右下角加上一个”+”号,如 ,表示PD以根据Autofix Script修复完成。
Global Script: 用于存放全局函数,在任何元模型的Check Model均可调用。
实现代码
Check Script: 用于检测Refence的建立正确与否。

注:PD会对每个模型进行检测(包括Package),所以如果读者希望通过程序来控制该模型是否被检测,只须在满足条件的语法段内加上%Check% = True (表示验证正确并跳过)即可。
Persistent Class持久类
对于POJO的持久类,必须为其每个类的属性增加Getter和Setter函数。扩展模型是基于语言模型之上的,也就是说,语言模型中的模板等内容均可在扩展模型中覆盖和重写。所以,在Hibernate扩展模型中采用重载的方法,扩展了Java语言模型的代码生成,保留了原先Java那部分代码,并在扩展模型中加上自己的Getter和Setter模版。
在Java语言模型中,代码生成是依靠%source%模版来完成Java代码的,同时有一个%initializers%模版实现当完成Attribute之后的一些初始化工作,所以在相同位置(Class元模型)的地方重写了%initializers%模版,代码如下:

在Attribute元模型中增加getterFunction 、setterFunction模版,代码如下:

然后在Class元模型中增加持久类的Generated Files,并在模版编辑框内输入%source%即可。
Generated Files
PD在每个元模型中提供了文件生成的功能。在Class元模型上右键选择Generated Files。在右边窗口中,在 File Name 下输入生成后的文件名。由于Hibernate映射文件的文件名与类名相同,故输入%mappingFilename%,同时建立mappingFilename 模版,并输入%Code%.hbm.xml。
注:所有的元模型都继承于NamedObject(NamedObject继承于BaseObject),在NamedObject中存放了各种元模型的标准属性,比如:模型名称(Name)、代码名称(Code)、注释、描述等等。所以,为了取到类的名称,就在类元模型下输入%Code%.hbm.xml,那么PD会根据代码名称为每个类建立相应的文件(前提是该类可以被生成,即已持久化)。
Model
Model元模型中主要实现对Configuration Mapping的连接信息的配置,诸如,JDBC等。所用到的方法也就是Extended Attribute和Mapping代码模版。由于篇幅原因,不一一列举,读者可以参考刚才所讲,或者可以在PD安装目录下运行pdvbs11.chm来获取帮助。
Task
Task在代码生成完毕之后被激活,然后PD会依次序执行选中的任务。扩展了Hibernate模型,增加了ANT的Lib路径,生成的目录名称等等选项。在Generation\ Options下建立新的选项即可,类似于Extended Attribute。调用Options选项时,输入如下代码:%GenOptions.选项名% 即可获取。
对于Task,希望能够借助ANT的build.xml配置进行自动测试。在PD中,JAVA语言模型已经提供了ANT的build.xml的自动生成并预留接口 (customExecuteTarget、customerProperties、customTaskDefs三个模版) ,目的为了能让扩展模型来重载,有兴趣的读者可以查看Java语言模型(LanguageEdit Current Object Language,浏览Java::Profile\Model\Templates\Ant\antTemplate)。
建立Task:
在Generation\Tasks上右键,选择New。输入Task Name(就是真正执行的显示名),取名为Run Unit Test。在下面的表格中选择已建立的Command,如果没有建立,则可以在Commands上新建。
Run Unit Test Command代码:

说明:
.execute_command为宏命令,用于执行外部的程序。
.execute_command '(' <cmd> [',' <args> [',' <mode>]] ')'
第一个参数为主命令,这里是CMD
第二个参数为主命令的参数,这里是/K ANT.BAT JUNIT
第二个参数为管道类型,PD提供cmd_ShellExecute和cmd_PipeOutput两种方式。前者采用独立的进程方式,后者将会阻塞PD直到任务完成,并且结果将显示在PD的Output窗口内,如图10所示。
