在ejb 2.0局部引用和容器管理关系出现之前,通常把实体ejb用于模型粗粒度域对象。这主要是由于与远程通信有关系统开销并阻止了细粒度访问企业层的客户层对象。粗粒度设计的性能通过实现数值对象而促进改善,压缩所有的数据也就是说在客户层和企业层之间传递数据。使用有大量域对象的复杂系统,即使这么样能提供一个第一流的和高度执行设计,这个设计导致在系统内出现过多的数值对象。这同样也创建在企业层和客户层之间的紧密连接。同样,在ejb出现之间,bean提供者不得不明确地提供用于维护域对象之间联接的程序。在一个有在域对象之间的复杂关系的情况中,数值对象的设计变得很复杂。在使用ejb开发企业应用程序的过程中,容器管理关系和局部引用的出现开启了令人兴奋的新途径。在本文中,我将带你使用ejb 2.0的强大方法连同bean组件和jaxp创建动态的基于数据结构的xml,可以在你的企业层和表现层之间传递信息。
从企业层到客户层传递数据的过程中使用xml,可以帮助你实现在的应用程序中的多种宽松连接;然而,当你把新的域对象添加到实体型中时,你可能需要添加用于创建新dom构架的类来添加该实体。在文中,我们将开发一个框架来动态地遍历容器管理和给定的局部ejb有关的域,并且创建一个可以在应用程序的多个层之间传递的xml件。这个方法将有以下优点∶
在企业层和客户层之间促进宽松连接。
便于管理域对象之间关系。
从系统中除去复杂数值对象因为xml是由动态地遍历cmp和cmr域产生的,当它们添加新对象到域模型中时,bean提供者不必创建新的用来创建新的dom构架的对象类。
ejb 2.0局部引用促进访问bean组件;bean组件与局部引用结合可以含于与其他的被容器管理的bean的关系。举例来说,在一个帮助系统中,userejb可以有与servicerequestejb的一到多双向关系和与productejb的一到一的单向联系以及与servicerequesthistoryejb的一到的双向关系。userejb同时可以有与phoneejb一到多的双向关系。这样,使用ejb 2.0局部引用和容器管理关系,你可以设计一套复杂的有关体。容器管理持久性和关系域是在bean类中使用抽象存取程序方法定的。用于关系域的存取程序方法要么返回一个集合要么返回定义这个系的bean的本机接口,这还取决于这个关系集的容量。这些存取程序法可以通过bean组件的本机接口展示。ejb 2.0的深入研究超出了本文范围,请参阅ejb 2.0的规范。
一个效率高的设计模式应该通过外观组件展示你的应用程序的使用案例并且不准从客户层中直接访问实体组件。回到我们的帮助系统的例子中来,其中的一个使用案例是取得给定用户的详细资料。外部组件可以查找需要的用户实体组件,并且通过容器管理持久性与关系域取得所需数据并把它返回表现层。
用于数据传送对象的一个显而易见的选择就是简单的java bean。userbean可能有表示持久性与关系域的属性。这种关系域要么是java.util.collection要么是其他的取决于这种关系的bean组件。userbean可能有servicerequestbean和phonebean集。servicerequestbean可能有一个productbean和许多servicerequesthistory bean组件。此外,这些bean组件还可能还有简单的string或者表现容器管理持久性域的基本属性。这个选择的主要的不利之处就是使你的实体模型更加复杂,使你的数据传送对象bean层次更加复杂,还将在你的服务(企业)层和消费(表现)层之间创建紧密连接。研究一下这个关系的复杂的层次,一个更好的选择是使用xml dom对象作为数据传送对象。你的组件将产生oeg.w3c.dom.document对象类型并且你的表现组件使用xml的jsp自定义标记和xslt文件来“消费”它们。
现在,下一个问题是∶怎么从cmp局部bean引用中创建xml文件?我们可以使用一个基于用于创建不同的类型的dom组件的方法的工厂;然而,这将创建过多的“工场”组件,并且你可能需要添加新的"工场"组件作为你的实体模型扩展。我们需要的是一个可以使用实体局部对象,引导容器管理关系和创建动态dom构架的公用程序。这个公用程序将负责在双向关系中循环引用,以避免无限的循环和深入导航关系元素。
接下来我们将演示一个可以提供这个功能的公用程序类。
package ws.business.service.util; public domgenerator(string docelementname, int drilldowndepth) { try { } public document getdom(ejblocalobject local) { try { }catch(illegalaccessexception ex) { } private void populateelement(element parent, ejblocalobject local) 把当前的局部引用添加到连接引用列表中。 for(int i = 0;i < properties.length;i++) { try { }catch(classcastexception ex1) { 如果抛出一个classcastexception,就要试着把属性强制转换成collection collection colprop = (collection)prop; 如果当前的drilldown深度大于设置的drilldown深度,跳出处理。 while(it.hasnext()) { 得到collection中的每个局部引用。 child.appendchild(grandchild); populateelement(grandchild, locprop); } }catch(classcastexception ex2) { 如果抛出一个classcastexception的话,属性是一个持久性域并且要把它 } } } iterator it = _circularref.iterator(); } } |
下面的代码片断演示如何使用这个类:
user local = userhome.findbyprimarykey("1"); <requests> <phones> </user> |
在本文中,我们详细研究了一个模型用于在一个j2ee应用程序的企层和表现层之间传递复杂数据。表现层可以交付xml数据,这些数据在企业层上生成的,被使用xslt或者xml jsp自定义标记交付到客设备上。
当你添加新的定义到你的域模型中的时候,你唯一需要做的事情就是使用精细局部实体bean定义,然后使用容器管理关系定义关系。dom生成程序提供一个一般的方法生成动态的xml文件。
然而,就象任何其他的设计方案,这个方法也有它的缺点。一个明显的方面就是开发人员经常担心基于xml的数值对象的性能。在一台1ghz cpu, 256mb内存,操作系统为windows me的机器中,运行应用软件服务器(wls 6.1)和数据库服务器,上述对一千条纪录的记录集的操作以及处理多元联系用了不到0.5秒钟。第二个明显的方面就是类型安全性。因为xml提供了数据抽象化的最高级别,属性的结点值和文本节点总是被当做字符串。如果你打算在从企业层上检索回来的数值对象上进行进一步的事务操作的话,最好就使用java bean组件。然而,xml模式提供了一个功能强大的机制,用于加强xml文件的类型安全性。在两种情况下都要使用局部实体对象作为域对象。
这个方法最大的缺点就是没有模型化基于xml数据的明确定义的方法。我还没有看见过任何模型化使用xml的域对象关系的uml注释或者通用的规范定义。
闽公网安备 35060202000074号