业务层设计之六(CompositeEntity) |
Composite Entity(复合实体) 问题 需用EntityBean实现业务领域概念模型.使用EntityBean实现业务对象会产生一些问题。 1. 需要决定用远程EntityBean还是本地lEntityBean(EJB1.1不可用)。远程EntityBean 会增加网络负载。在EJB 2.x 容器中,本地EntityBean与它的客户端处于同一JVM中, 这就能进一步控制系统性能和网络负载.但是与POJO业务对象相比,本地EntityBean 还不够高效,EJB容器还要透明地提供很多优化和很多服务,比如安全,事务等等。 2. 如何实现EntityBean业务对象的持久化存储。可以用CMP, 但是如果有一个以前遗留 的持久化实现或者需要实现某些独特的需求,就要用BMP了。 3. 业务对象的关系实现。可以使用"容器-管理关系"和"bean-管理关系"实现.只有使用了 CMP才能用上CMR, 但CMR还要求所有相互关联的EntityBean都得是本地EntityBean。 动机 1. 需要避免远程entity bean的缺点(比如网络负载和远程的entity bean关系)。 2. 需要用定制的或者是以前遗留的持久化实现,完成bean-管理持久化(BMP)。 3. 在使用entity bean实现业务对象时,需要高效地实现对象之间的父-子关系。 4. 需要用entity bean封装并聚合现存的POJO业务对象。 5. 需要充分利用EJB容器的事务管理和安全功能。 6. 需要把数据库的物理设计对客户端封装起来。 结构 使用复合实体,结合本地entity bean和POJO,实现业务对象的持久化。 client ----> CompositeEntity(LocalEntityEJB) ---->DependentBO(entity, POJO) 客户端: SessionFacade, AppService etc. 复合实体: 一般以LocalEntityBean实现父业务对象,其中还包含从属对象。 从属服务对象: DependentBO依靠父对象管理LifeCycle。从属对象还可以包含其他从属 对象。这样一来,整个复合实体中就可能包含一棵对象树。从属对象可以实现为本地 EntityBean,也可以实现为POJO(如果使用CMR,从属对象就只能是本地EntityBean)。 EJB容器: 参见EJB容器如何通过load,store,activae,passivate方法和EntityBean交互。 示例 Resouce业务对象是通过复合实体模式实现的,它与从属关系的"一对多"关系是用集合实现。 public class ResourceEntityBean implement EntityBean { public String employeeId; public String lastName; public String firstName; public String departmentId; // BlockOutTime(缺勤时间集)从属对象的集合。 public Collection blockOutTimes; // SkillSet(技能集)从属对象的集合 public Collection skillSets; private EntityContext context; public String ejbCreate(ResourceTO resource) throws CreatException { try { this.employeeId = resource.employId; setResourceData(resource); getResourceDAO().create(resource); } catch (Exception e) { throw new EJBException("Reason:"+.......); } return this.employeeId; } public String ejbFindByPrimaryKey(String primaryKey) throws FinderException { // return getResourceDAO().findResource(primaryKey); } public void ejbRemove() { // 删除从属对象 // getSkillSetDAO().deleteAll(employId); // skillSets = null; // getBlockOutTimeDAO().deleteAll(employId); // blockOutTimes = null; // 从持久化存储中删除资源 //resourceDAO.delete(employeeId); } public void setEntityContext(EntityContext context) { this.context = context; } public void unsetEntityContext() { context = null; } public void ejbActivate() { employeeId = (String)context.getPrimaryKey(); } public void ejbPassivate() { employeeId = null; } public void ejbLoad() { // 装载资源 ResourceDAO resourceDAO = getResourceDAO(); setResourceData((ResourceTO)resourceDAO.findResource(employeeId)); // 如果必要,装载其他从属对象 } public void ejbStore() { // 存储资源信息 getResourceDAO().update(getResourceData()); // 如果必要,保存其他从属对象 } public void ejbPostCreate(ResourceTO resource) {} public ResourceTO getResourceTO() { ResourceTO resourceTO = new ResourceTO(employeeId); resourceTO.lastName = lastName; resourceTO.firstName = firstName; resourceTO.departmentId = departmentId; .......... return resourceTO; } public void setResourceData(ResourceTO resourceTO) { employeeId = resourceTO.employeeId; lastName = resourceTO.lastName; ........... } public Collection getBlockOutTimesData() { return blockOutTimes; } public Collection getSkillSetsData() { return skillSets; } public void addBlockOutTimes(Collection moreBOTs) { // 注意: moreBOTs是BlockOutTimeTO对象的 // moreBOTs.iterator(); blockOutTimes.add((BlockOutTimeTO)iter.next()); } public void addSkillSet(Collection moreSkills) { //同上 } public void updateBlockOutTime(Collection updBOTs) { Iterator botIter = blockOutTimes.iterator(); Iterator updIter = updBOTs.iterator(); while (updIter.hasNext()) { BlockOutTimeTO botTO = (BlockOutTimeTO) updIter.next(); while (botIter.hasNext()) { BlockOutTimeTO existBOT = (BlockOutTimeTO) botIter.next(); if (existBOT.equals(botTO)) { botTO.setDirty(); // 修改过的旧从属对象 botTO.resetNew(); // 不是一个新的从属对象了 existBOT = botTO; } } } } pubic void updateSkillSet(Collection updSkills) { // 同上 } } |
联系客服