Dorado 9 : 虚拟属性下拉选择(sample-center)

本案例的关键字是"性能"

一般情况下我们可以通过PropertyDef或Editor的mapping属性,做代码/名称的映射处理。但是仔细考虑其原理:将所有的代码/名称下载到客户端,并在客户端实现映射。

这个原理带来的弊端是:如果系统的代码/名称的数据量很大,例如超过1万,那么不仅这1万的数据的下载会对网络传输带来负担,同时也会对浏览器的JS映射效率带来挑战。不同机器硬件和软件环境配置会导致差异性非常大的执行效率。如果超过10万,则可能浏览器的下载的耗时变得不可接受,同样浏览器代码/名称映射的时间也会变得不可接受。而在系统开发测试阶段由于测试库数据的不完整性,导致数据量不太大,页面的测试效率也不错,但是如果直接将这个页面交付出去,并部署到生产环境中,最后的执行效果可能是你根本无法想象的。

因此本例以虚拟属性下拉选择范例,对这个问题的解决方案提供一种标准的建议。同时这也是你在一个非dorado开发环境下解决由于代码/名称映射问题带来的性能问题的解决思路。

基本实现原理:

利用虚拟属性为数据实体添加一个额外的属性用于暂存和显示"名称",而数据实体中原本存在的"代码"属性则被隐藏起来(在一些系统设计中VO或DTO会做类似的工作)。此种做法有以下三个要点:

  • 服务端的逻辑需要根据"代码"属性的值填充好"名称"属性,以便于界面能在打开时正确的显示"名称"。
  • 界面上利用下拉框等对"名称"属性进行选择式的编辑,确保用户在做出选择后前台逻辑能够同时改写"名称"和"代码"这两个属性。
  • 在数据提交的处理逻辑中我们真正需要处理的通常是"代码"属性,"名称"属性的值往往被直接弃置。

下面详细说明实现过程。

名称显示

Order.java中有employeeId属性,没有employeeName属性:

但是我们期望看到的页面效果如下(其中的employeeId不显示,而是直接显示employeeName:

首先针对DataType增加一个employeeName的虚拟属性:

之后在DataProvider中提取数据的时候顺便初始化employeeName属性:

@DataProvider
public void getOrders(Page<Order> page) throws Exception {
	orderDao.find(page, "from Order");

	// 以下两行代码的作用是将一个普通Bean集合转换成一个Dorado数据实体集合。
	Collection<Order> orders = EntityUtils.toEntity(page.getEntities());
	page.setEntities(orders);

	// 此时通过迭代得到的已经是被动态代理过的Dorado数据实体了,虽然类型仍然是Order。
	// 我们可以向数据实体中设置虚拟属性的值
	for (Order order : orders) {
		EntityUtils.setValue(order, "employeeName", order.getEmployee()
				.getFirstName());
	}
}

通过EntityUtils实现虚拟属性的设置。

然后在AutoForm中添加employeeName对应的FormElement而不是employeeId

通过以上步骤,我们可以保证当网页上显示这个AutoForm的时候,其中的employeeName为对应employeeId的employeeName.

下拉框实现

下面我们再实现为输入而提供的下拉框,如果你的表单是只读或仅仅为Grid显示,不需要编辑的话,就不需要做下面的进一步开发。

为了方便输入,我们对employeeName提供下拉选择功能,界面效果如下:

本例采用DataSetDropDown实现,首先得配置好DataSet对象:

然后添加DataSetDropDown:

最后设置AutoForm中formElement的trigger属性为ddEmployees:

由绑定trigger的是employeeName,employeeId被隐藏,我们当然希望当用户选择一个employee的时候,自动的将隐藏的employeeId的值与employeeName的值一起修改。则可以通过DataSetDropDown的assignmentMap属性设置:

employeeId=id,employeeName=firstName

assignmentMap是下拉选择的实体对象与表单所对应的实体对象属性赋值逻辑关系的映射设置。

由于DatasetDropDown中下拉的数据实体中工号值的属性为id,姓名值的属性firstName,则assignmentMap的配置就不难理解。多个属性赋值时用逗号隔开。