6.BM??

2012-01-05 13:46:50by SeaCat

BM继承

BM继承概述

在Aurora框架中,可通过一个BM配置文件同时实现数据的查询,新增,修改等操作。但是,在实际应用中,往往会碰到这样的情况:执行查询时需要10个字段,并需要join其他的一些表,而执行插入时只需要6个字段;或者,一个BM在大多数查询时都适用,但在某种场合下又要加上额外的限制条件,而查询结果中的字段又是完全相同的。如果为这些应用场景都开发一个单独的BM,势必会有很多重复的成分,相同的配置散布在多个文件里,不仅开发效率低,也会带来维护的麻烦。

Aurora为BM提供了一种继承机制,与java语言中的继承类似,一个BM可以继承自另一个BM,从而自动获取父BM所有或部分配置,并可设置自己特有的属性。

与Java语言中的全盘继承所不同的是,BM可以通过设置继承模式,来有选择地继承父BM中的各种对象。例如,父BM中定义了10个字段,子BM中可以选择只继承其中的3个。下面分别说明BM的两种继承模式。

引用模式

在引用模式中,子BM必须显示地定义哪些对象是希望从父BM中继承过来的。例如:

test/emp_for_lov.bm
<bm:model xmlns:bm="http://www.aurora-framework.org/schema/bm" alias="t2" extend="test.emp" extendMode="reference">
    <bm:fields>
        <bm:field name="empno"/>
        <bm:field name="employee_name"/>
    </bm:fields>
</bm:model>	    
	    

这里,该BM通过extend="test.emp"属性,声明从test.emp继承而来,并通过extendMode="reference"属性,声明继承模式为引用模式。在fields部分,定义了两个field,并且只设置了name属性。这意味着,该BM将从test.emp继承empno,employee_name这两个指定的字段。字段上的属性,如dataType,databaseType等也将一并继承过来。test.emp的其他字段,由于没有在子BM中声明,就不会出现在子BM中。

查看通过该BM生成的查询SQL,可以看到:

SELECT t1.empno,t1.ename AS employee_name,dept.dname AS department_name
FROM emp t1
	LEFT OUTER JOIN dept dept ON t1.deptno = dept.deptno
	    

由于子BM只声明了两个字段,所以select的字段部分只有两个。但是,父BM中定义的relations及ref-fields依然在生效。下面将详细解释其中的原理。

引用模式中集合对象的处理

BM中有很多集合对象,如fields是field的集合,ref-fields是ref-field的集合,query-fields是query-field的集合,等等。在reference模式下,对于父BM的集合对象,处理规则如下:

  • 如果子BM中对某个集合没有任何设置,则自动从父BM中完全继承此集合。例如,上面的例子中,子BM没有ref-fields,primary-key和relations标记,所以将会从父BM中完全继承这些内容。

  • 如果子BM中对某个集合只设置了空的顶层元素,那么子BM中将不会包含父BM中所声明的此集合中的任何元素。例如,在上例中,如果在子BM中放置<bm:ref-fields />标记,那么子BM将不包含任何ref-field,尽管父BM已经声明过几个ref-fields。

  • 如果子BM设置了某个集合,并在其中也设置了子节点,那么,将会自动合并父BM在此集合中具有相同name属性的节点。如果父BM没有对应name属性的节点,那相当于子BM在此设置了一个全新的节点。对于父BM中存在,子BM中不存在的子节点,将不出现在子BM中。

我们再看一个例子,上面的子BM中,我们首先设置name="empno"的physicalName属性,改为另外一个字段名,再增加一个名为salary的field,然后在ref-fields部分设置一个父BM没有设置过的字段,最后再增加一个data-filter:

test/emp_for_lov2.bm
<bm:model xmlns:bm="http://www.aurora-framework.org/schema/bm" alias="t2" extend="test.emp" extendMode="reference">
    <bm:fields>
        <bm:field name="empno" physicalName="empno1_that_not_exists"/>
        <bm:field name="employee_name"/>
        <bm:field name="salary" expression="trunc(sal)"/>
    </bm:fields>
    <bm:ref-fields>
        <bm:ref-field name="new_dname" relationName="dept" sourceField="dname"/>
    </bm:ref-fields>
    <bm:data-filters>
        <bm:data-filter expression="mrg is not null"/>
    </bm:data-filters>
</bm:model>
	    

然后查看生成的查询SQL:

SELECT t2.empno1_that_not_exists AS empno,t2.ename AS employee_name,trunc(sal) AS salary,dept.dname AS new_dname
FROM EMP t2
	LEFT OUTER JOIN dept dept ON t2.deptno = dept.deptno
WHERE mrg is not null
	    

由于empno字段的physicalName属性在子BM中被重新定义,所以生成的SQL中以子BM中设置的字段名为准。salary字段是子BM新定义的,父BM中没有该字段,也会出现在生成的SQL中。由于ref-fields集合在子类中被设置,所以会只出现子BM设置了的ref-fields;而relations集合没有设置,所以relations部分完全继承父BM。由于子BM额外定义了data-filters,所以生成的SQL中多了一个where条件。

重载模式

在BM中,设置extendMode="override"来设置继承模式为重载模式。这种模式与Java语言的继承模式类似,子BM将继承父BM的所有设置,子BM设置的同名属性、节点将覆盖父BM的设置。实例:

test/emp_for_lov3.bm
<bm:model xmlns:bm="http://www.aurora-framework.org/schema/bm" alias="t2" extend="test.emp" extendMode="override" needAccessControl="false">
    <bm:fields>
        <bm:field name="empno" physicalName="empno1_that_not_exists"/>
        <bm:field name="employee_name"/>
    </bm:fields>
    <bm:ref-fields>
        <bm:ref-field name="new_dname" relationName="dept" sourceField="dname"/>
    </bm:ref-fields>
    <bm:data-filters>
        <bm:data-filter expression="mrg is not null"/>
    </bm:data-filters>
</bm:model>
	    

除了extendMode属性,其他与emp_for_lov2完全一致。对应的查询SQL:

SELECT t2.empno1_that_not_exists AS empno,t2.ename AS employee_name,trunc(sal) AS salary,t2.job,t2.mgr,t2.hiredate,t2.deptno,t2.sal,t2.comm,dept.dname AS new_dname,dept.dname AS department_name
FROM EMP t2
	LEFT OUTER JOIN dept dept ON t2.deptno = dept.deptno
WHERE mrg is not null
	    

由于override模式下,所有设置都会从父BM继承,所以生成的SQL中包含test.emp定义过的所有字段。由于子BM对empno字段重新设置了physicalName属性,所以该字段对应的SQL以子BM为准。与前例相同,在子BM中添加的设置,如名为salary的field,以及data-filter,都会生效。子BM定义的ref-field,由于名称不一样,所以会与父BM定义的ref-field合并,同时出现在SQL中。

重载模式中集合对象的处理

在override模式下,对于父BM的集合对象,处理规则如下:

  • 如果子BM中对某个集合没有任何设置,则自动从父BM中完全继承此集合,这与reference模式相同。

  • 如果子BM中对某个集合只设置了空的顶层元素,如<bm:ref-fields />,那么子BM一样会继承父BM对该集合的所有设置,效果等同于没有设置这个顶层元素。

  • 如果子BM设置了某个集合,并在其中也设置了子节点,那么,将会自动合并父BM在此集合中具有相同name属性的节点。如果父BM没有对应name属性的节点,那相当于子BM在此设置了一个全新的节点。对于父BM存在而子BM没有定义的节点,也会被子BM所继承。

同名节点的属性处理

所谓同名节点,是子BM和父BM中,同一集合下,具有相同name属性的节点,例如fields下面中具有相同name的field。如果父节点和子节点都设置了相同的属性,那么以子节点的为准,如前面例子中,empno字段中的physicalName属性。如果父节点设置了某属性而子节点没有设置,则自动从父节点继承此属性。如果子节点设置了而父节点没有设置,一样以子节点为准。

这些规则同样也适用于BM的根节点:model。例如,父BM中设置了<bm:model alias="t1" >,子BM中设置了<bm:model alias="t2" >,那么最终的alias将是t2。

BM继承应用场合分析

以下就各种典型的应用场合,分析子BM应该如何设置。

  • 需要添加额外的字段:用override模式,在子BM中只定义要加的字段。

  • 需要更改字段的属性:如果父BM中所有的字段都要用,那么用override模式,否则用reference模式,在fields部分逐一设置需要继承的field及其name。然后,在fields中设置新的属性值。

  • 需要减少字段:用reference模式,否则用override模式,在fields部分逐一设置需要继承的field及其name。

  • 需要增加额外的查询限制条件,或可选查询条件:先根据fields部分的需求,确定用那种模式。对于override模式,直接在data-filters或query-fields部分增加新的data-filter,query-field即可。对于reference模式,如果父BM的data-filter或query-field是需要继承的,那么还需要逐一设置需要继承的data-filter或query-field子节点及其name属性。

  • 需要取消父BM中的某个限制条件:首先,父BM中的每个data-filter都应该用name属性命名,以便引用。如果是reference模式,在data-filters部分不设置父BM中对应的这个data-filter节点就可以了。如果是override模式,可以在子BM的data-filters下面设置同名data-filter,并将其expression属性设置为true(或等同于true的表达式,如1=1),效果相当于没有这个限制条件。

  • 需要取消父BM中关联的表,字段:用reference模式,然后在relations及ref-fields部分,不设置要取消的关系及字段。

  • 需要关联新的表,字段:不论用那种模式,在子BM的relations及ref-fields部分增加新的relation及ref-field,去关联新的表。

  • 需要更改某个relation所关联的BM名称或join type:不论用那种模式,在子BM的relations下面设置同名relation节点,并设置新的refModel或joinType属性。

Demo
    Attachments

      Comments

      1 Responses to the article
      1. [email protected] 留言于:2017年06月06日 13:43
        好东西。
      发表评论