在实际应用中,为了达到逻辑重用的目的,会使用嵌套的AM。
在Root AM和Nested AM中都有各自的VO,在一个页面中,可能同时用到了不同AM的不同的VO,那么当一个AM提交时,另一个AM是否也会提交呢?
其实,这个问题的产生来自于一个客户的真实情况:
在一个页面中,有多个Tab页签,每个Tab页签中都一个表单和保存按钮。
用户可以选择修改Tab页签中的表单,于是就出现了这种情况:
用户修改了某个Tab页签中的表单,没有马上提交,接着修改另一个Tab页签中的表单,并点击这个Tab页签中的保存按钮,结果发现前一个页签中的修改也被成功提交了。
为了更加清楚阐述这个问题,我做了一个实验。
实验步骤主要如下:
1. 创建并定制化AppModule,包含JobVO和EmployeeVO。
增加3个方法,代码如下:
public void createJob() {
JobsViewImpl jobVO = (JobsViewImpl)getJobsView1();
JobsViewRowImpl newJob = (JobsViewRowImpl)jobVO.createRow();
jobVO.insertRow(newJob);
newJob.setJobId("Oracle");
newJob.setJobTitle("CEO");
newJob.setMinSalary(new Integer(10000));
newJob.setMaxSalary(new Integer(50000));
getTransaction().commit();
}
public void deleteJob() {
JobsViewImpl jobVO = (JobsViewImpl)getJobsView1();
JobsViewRowImpl currentJob = (JobsViewRowImpl)jobVO.getCurrentRow();
jobVO.removeCurrentRow();
getTransaction().commit();
}
public void saveEmployee() {
getTransaction().commit();
}
2. 创建并定制化NestedAppModule,包含JobVO。
(1)创建
(2)定制化
增加2个方法,代码和AppModule前2个方法相同,略。
3. 把NestedAppModule加入到AppModule中。
(1)
(2)完成后的Data Control
4. 创建页面,内容如下:
(1)拖放root AM DC中的JobView1和EmployeeView1,都选择Form。
(2)为Job Form 添加两个Button: Create和Delete。代码如下:
public String rootAMCreate_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("AppModuleDataControl");
AppModuleImpl service = (AppModuleImpl)am;
service.createJob();
return null;
}
public String rootAMDelete_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("AppModuleDataControl");
AppModuleImpl service = (AppModuleImpl)am;
service.deleteJob();
return null;
}
(3)为Employee Form 添加一个Button: Save。代码如下:
public String rootAMSave_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("AppModuleDataControl");
AppModuleImpl service = (AppModuleImpl)am;
service.saveEmployee();
return null;
}
(4)拖放root AM DC中的NestedAppModule1中的JobView1,选择Form。
(5)同样也为这个Job Form 添加两个Button: Create和Delete。代码如下:
public String nestedAMCreate_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("AppModuleDataControl");
AppModuleImpl service = (AppModuleImpl)am;
NestedAppModuleImpl nestedService = (NestedAppModuleImpl)service.getNestedAppModule1();
nestedService.createJob();
return null;
}
public String nestedAMDelete_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("AppModuleDataControl");
AppModuleImpl service = (AppModuleImpl)am;
NestedAppModuleImpl nestedService = (NestedAppModuleImpl)service.getNestedAppModule1();
nestedService.deleteJob();
return null;
}
(6)直接拖放Nested AM DC中的JobView1,选择Form。
(7)同样也为这个Job Form 添加两个Button: Create和Delete。代码如下:
public String topNestedAMCreate_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("NestedAppModuleDataControl");
NestedAppModuleImpl service = (NestedAppModuleImpl)am;
service.createJob();
return null;
}
public String topNestedAMDelete_action() {
ApplicationModule am = ADFUtils.getApplicationModuleForDataControl("NestedAppModuleDataControl");
NestedAppModuleImpl service = (NestedAppModuleImpl)am;
service.deleteJob();
return null;
}
5. 运行
为了说明问题,我测试了如下场景:
(1)修改Employee表单的某个属性,但并不点击Save按钮提交,而是点击Nested AM inside Root AM中的Job表单的Create按钮提交。
现象:被修改的Employee 表单的属性被成功提交入库。
解释:Employee VO属于Root AM,选择的Job VO属于Nested AM inside Root AM,它们使用同一个Transaction。
因此当修改前一个表单后,虽然提交的是另一个表单,前一个表单的数据也被提交了。
(2)修改Nested AM inside Root AM中的Job表单的某个属性,但并不点击Create/Delete按钮提交,而是点击Root AM中的Employee表单的Save按钮提交。
现象:被修改的Job 表单的属性被成功提交入库。
解释:同(1)。
(3)修改Employee表单 的某个属性,但并不点击Save按钮提交,而是点击 Nested AM outside Root AM中的Job表单的Create按钮提交。
现象:被修改的Employee 表单的属性并没有被写入数据库。
解释:Employee VO属于Root AM,选择的Job VO属于Nested AM outside Root AM,相当于是一个Root AM,二者是平行AM的关系,各自管理各自的Transaction。
当修改前一个表单后,而提交的是另一个表单,前一个表单的数据并没有被提交。
(4)修改Nested AM outside Root AM中的Job表单的某个属性,但并不点击Create/Delete按钮提交,而是点击Root AM中的Employee表单的Save按钮提交。
现象:被修改的Job 表单的属性并没有被写入数据库。
解释:同(3)。
6. 结论
(1)Nested AM与Root AM 使用的是同一个Transaction,都是Root AM中的Transaction,无论使用哪个AM提交,另一个AM中的VO也会被提交。
(2)多个Root AM之间的Transaction互不干涉,各自管理自己的。
(3)所以,要想避免提交本不想提交的表单,该表单所对应的VO的AM必须是Root AM。
7. 补充说明
以上提交方法都是使用getTransaction().commit(); 。
经过进一步测试,使用DataControl提供的Commit操作(拖放到页面上),实验结果和上述测试相同。
Project 下载:ADF_NestedAM_Transaction.7z
没有评论:
发表评论