动态属性 API

模型

动态属性实现了 实体-属性-值 模型。

dynattr diagram
  • Category 定义对象的分类,以及每个分类对应的一组动态属性。分类需要分配给某些实体类型。

    例如,有一个 Car 类型的实体。我们可以定义两个分类:Truck(卡车)Passenger(乘用车)Truck 分类包含 Load capacity(载货量)Body type(车身类型) 属性;Passenger 分类包含 Number of seats(座位数)Child seat(儿童座位) 属性。

  • CategoryAttribute 定义某个分类中的动态属性。每个属性使用一个确定的类型描述单一字段。必需的 code 字段包含属性的系统名称。name 字段包含可读的属性名称。

  • CategoryAttributeValue - 特定实体实例中动态属性的值。动态属性值保存在专门的 SYS_ATTR_VALUE 表中。表中每一行记录与一个实体通过 ENTITY_ID 列关联。

一个实体实例可以拥有该实体类型关联的所有分类中的属性。因此,如果为上面提到的 Car 实体创建两个分类,则可以为 Car 实例指定两个分类中的任何属性。

如果需要将实体实例划分为归属某一特定分类,例如,车可以是卡车或乘用车,实体必须实现 Categorized 接口。此时,实体带有分类的引用,且只有该分类的动态属性。

读写动态属性

动态属性值的读写通过 DataManager 处理。使用下列方法之一可以设置加载实体的动态属性:

  • LoadContextsetHint(DynAttrQueryHints.LOAD_DYN_ATTR, true) 方法。

  • 流式 API 的 hint(DynAttrQueryHints.LOAD_DYN_ATTR, true) 方法。

默认情况下,不加载动态属性。但是,DataManager 会保存 save() 方法中收到实体包含的动态属性。

动态属性值可以通过 EntityValuesgetValue() / setValue() 方法进行读写。动态属性编码需要使用 + 前缀,示例:

@Autowired
private DataManager dataManager;

public void increaseLoadCapacity(Car car, int value) {
    Car carLoad = dataManager.load(Car.class)
            .id(car.getId())
            .hint(DynAttrQueryHints.LOAD_DYN_ATTR, true)
            .one();
    Double capacity = EntityValues.getValue(car, "+TruckLoadcapacity");
    EntityValues.setValue(car, "+TruckLoadcapacity", capacity + value);
    dataManager.save(car);
}

实际上,在应用程序代码中,我们很少需要直接访问动态属性值。任何动态属性都可以自动在 TableForm 组件中展示,只要这些组件绑定的数据容器中实体带有动态属性。可以在配置动态属性时,指定界面和组件中 属性可见性