在设计模式3中我们看到使bean从struct继承后使得代码大幅缩水并且所有的字段都可定义为cmp字段。这里,我们可以更进一步修正setdata()和getdata()的实现方法来减少代码量。我们为这个struct增加一个方法。
由于entity bean是从struct继承下来的,在bean的实现类中也一样可以引用copyfrom()方法,当然,必须注意的是,这个copyfrom()方法并不是一个商业方法,它不需要在bean的远程接口中暴露给调用者。现在,getdata()和setdata()方法可以简化更进一步的简化。
这里把this作为一个参数传入copyfrom()。由于enttity bean从struct继承而来,于是这个entitty bean便可以作为一个struct传入。EJB容器并不赞成把this指针作为一个参数传递因为在两个控制线程中同时访问一个bean的实例可能会引起事务冲突。但事实上我们所做的并没有违背这个原则,因为我们的并没有在bean之间传递this的引用并且也没有引用任何可能引起事务冲突的方法。
对于一个映射到有很多列的表的entity bean,这种实现方法的优点是使bean实现类的代码非常简单。这种设计模式使得代码及其精简,可读性和可维护性也大大增强。任何数据库的修改都只需要修改作为基类的struct,而几乎不需要修改bean的代码。把这种改变从struct分离出来,当cmp字段发生改变时需要修改部署描述符。这就使得开发时能够更好的适应设计的改变。这里,还是没有实现bean之间的关系,这将在设计模式5中解决。
:
就像我们在设计模式4中看到的, Entity Bean的实现大小被缩减到在ejbCreat(), getData()and setData()方法中的仅仅几行,不管CMP字段的数目.下一步是建模公司和雇员的Entity Beans,这个有点繁琐而且建议读者先对borland公司的<EJB程序员指南>的OR Mapping和高级CMP有所了解.对这个关系建模根本不需要对结构的代码变化,然而Entity Beans实现类需要一点点修改来反映两个实体间的关系,鉴于此Deployment Descriptor需要有小的修改.
象以前, Entity Bean从结构继承,下面是公司Entity Bean的代码片段:
public class CompanyBean extends CompanyStruct implements EntityBean { EntityContext entityContext; // CMP for all fields in the CompanyStruct public java.util.Collection employees; //one-to-many //rest of the code including getData() and setData() public java.util.Collection getEmployees() { return employees; } } |
下面是雇员Entity Bean的程序片段:
public class EmployeeBean extends EmployeeStruct implements EntityBean { EntityContext entityContext; //CMP for all fields in EmployeeStruct EXCEPT //the comId public Company company;//remote reference to company } |
在上面的程序片段中,雇员Entity Bean从雇员结构继承,雇员结构本身有一个字段comId表示雇员和公司之间的的外键,在所有的前面的设计模式中,这个字段是CMP的.而在设计模式5中这个字段用在Deployment Descriptor中un-checking的方法从CMP中去掉.而对公司Entity Bean的远程引用现在是CMP的.现在的问题是怎么在getData()和SetData()方法中更新公司Entity Bean的引用,当这些方法只get和set comId(在设计模式上下文中没有被CMP)的值.简单的说,过程的结构没有变化并且字段comId(不再CMP)在RPC中被拷贝到Entity Bean和从Entity Bean拷贝出来.需要的是对公司Entity Bean的远程引用在必须被写入数据库和从数据库读出时更新.我们需要用ejbLoad()和ejbStore()方法在Entity Bean实现类中为我们完成这项工作.在雇员Entity Bean中的ejbLoad()方法的代码片段如下:
public void ejbLoad() { try { comId=(company ==
null)?null:(Integer)company.getPrimaryKey(); } catch (Exception e) { //throw some runtime exception (e.g. EJBException) } } |
以上代码几乎不需要解释.当数据被从数据库中读出(在事务的开始时候),comId(不是CMP)字段在雇员Entity Bean被set.因此当getData()方法被调用时,返回的结构将包含正确地comId的值.在雇员Entity Bean中的ejbStore()方法如下:
public void ejbStore() { try { company = (comId == null)?null:beanGlossary.getCompanyHome().findByPrimary Key(comId); } catch (Exception e) { //throw some runtime exception (e.g. EJBException) } } |