| 5.??BM?????2012-01-05 13:44:31by SeaCat Aurora可以看做是一个面向Feature的框架。所谓Feature,就是指可以重复使用的某种功能或特征。我们先来看一个例子。在企业应用中,经常需要在数据中记录更新信息,例如记录的创建人,创建时间,最后更新人,最后更新时间等。反应到数据库表结构上,就是大多数业务数据表都会有created_by,creation_date,last_updated_by,last_update_date等这样几个字段。每条记录在创建或更新的时候,都应该维护这几个字段。比如,创建记录时设置created_by等于当前登录用户的id,creation_date等于系统日期。 如果用单纯的O/R Mapping的思路去建模,这样特性很难做出合理的可重用设计。如果将这个特性封装在父类中,要求每个有此特性的业务实体都继承指定的父类。对于Java这样的单继承语言来说,一定会遇到某些业务实体必需从其他的父类派生,或者某些业务实体需要从父类派生,但又不需要这种特性的情况。这时,在子类coding就不可避免。对于Hibenate这样的O/R Mapping工具来说,如果出现这种具有一定共性的需求,对于应用开发人员来说,除非对Hibernate的源代码非常熟悉,否则就很难在短时间内扩展Hibernate,去实现这种特性。 Aurora的BM提供了一种基于配置的,声明式的功能扩展机制。以前面的emp.bm为例,我们在配置文件中增加一段feature配置: <?xml version="1.0" encoding="UTF-8"?> <bm:model xmlns:bm="http://www.aurora-framework.org/schema/bm" xmlns:f="aurora.database.features" alias="e" baseTable="EMP" needAccessControl="false"> <bm:fields> <bm:field name="empno" databaseType="BIGINT" datatype="java.lang.Long" insertExpression="(select max(empno)+1 from emp)"/> <bm:field name="employee_name" databaseType="VARCHAR" datatype="java.lang.String" physicalName="ename"/> <bm:field name="job" databaseType="BIGINT" datatype="java.lang.String"/> <bm:field name="mgr" databaseType="BIGINT" datatype="java.lang.Long"/> <bm:field name="hiredate" databaseType="DATE" datatype="java.sql.Date"/> <bm:field name="deptno" databaseType="BIGINT" datatype="java.lang.Long"/> <bm:field name="sal" databaseType="FLOAT" datatype="java.lang.Long" updateExpression="trunc(${@sal})"/> <bm:field name="comm" databaseType="FLOAT" datatype="java.lang.Long"/> <bm:field name="last_updated_by" databaseType="BIGINT" datatype="java.lang.Long" forInsert="false" forceUpdate="true" updateExpression="${/session/@user_id}"/> </bm:fields> <bm:primary-key> <bm:pk-field name="empno"/> </bm:primary-key> <bm:relations> <bm:relation name="dept" joinType="LEFT OUTER" refModel="test.dept"> <bm:reference foreignField="deptno" localField="deptno"/> </bm:relation> </bm:relations> <bm:ref-fields> <bm:ref-field name="department_name" relationName="dept" sourceField="dname"/> </bm:ref-fields> <bm:features> <f:standard-who/> </bm:features> </bm:model> 在BM的最后,声明了features部分,并在其下设置了一个名为standard-who的feature。增加了这个设置以后,再看通过BM生成的insert,update语句,可以看到自动多出了对前面几个追溯字段的处理: INSERT INTO EMP ( ...,CREATED_BY,CREATION_DATE,LAST_UPDATED_BY,LAST_UPDATE_DATE) VALUES ( ..., ${/session/@user_id},sysdate,${/session/@user_id},sysdate)
UPDATE EMP e SET .... , e.LAST_UPDATED_BY=${/session/@user_id},e.LAST_UPDATE_DATE=sysdate WHERE e.empno = ${@empno}
如果表中的standard who字段的名字与缺省的不一致,可通过standard-who标记的属性进行配置: <f:standard-who createdByField="create_user_id" creationDateField="create_time" lastUpdatedByField="updated_user_id" lastUpdatedDateField="update_time" userIdPath="/session/@user_login_id"/>
Aurora框架提供了一种机制,可以在配置文件中放入任意xml标记,并将这个标记和某一个或某些java class关联在一起。进而,这些java class会在框架处理数据的过程中,选择合适的切入点,介入处理过程,对中间数据进行加工、转换,从而实现各种可扩展的特性。对于上面的例子来说,实现standard-who标签的java class,在生成实际SQL之前接管控制,自动在BM中添加4个standard who字段。这样,生成的insert,update语句中,就会多出standard who字段的处理。 对于这个简单的例子,虽然说也可以要求开发人员在自己的BM中都手工加上这四个字段,但有可能会有人失误,少放置了某个字段,或者将某个字段的名称,数据类型拼写错误。以standard-who标签的方式来配置,由于只涉及一个配置点,出错的几率大大减少。更重要的是,这种具有普遍性的业务需求的实现,将集中于一处,更有利于维护。如果今后实现standard who的机制发生改变,例如不是直接存在业务数据表中,而是单独存在一个另外的表,那只需要开发一个新的java class,按新的数据结构去生成SQL语句,并将其与standard-who标签关联在一起就可以,不用去修改已经存在的所有BM。 Demo Attachments |
Comments
1 Responses to the article