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) {
// 同上
}
}
|