第一个设计模式非常简单。一个公司和雇员的Entity Bean和下面给出的Entity Bean的代码片断是类似的。它们是由jbuilder4的EntityBean模版生成的。所有的字段都声明为public的cmp字段。
Code snippet for Company Entity Bean
public class CompanyBean implements EntityBean {
EntityContext entityContext;
public Integer comId; //the primary key
public String comName; //the company name
public String comDescription //basic description
public Timestamp mutationDate //explained later
public Integer ejbCreate(<params>) throws
CreateException {
return null;
}
//various get() and set() for every column/field
// which are exposed in the Remote Interface as well Code snippet for Employee Entity Bean
public class EmployeeBean implements EntityBean {
EntityContext entityContext;
public Integer empId; //the primary key
public Integer comId; //the company foreign key
public String empFirstName; //the employee firstname
public String empLastName; // the employee lastname
public Timestamp mutationDate; //explained later
public Integer ejbCreate(<params>) throws
CreateException {
return null;
}
//various get() and set() for every column/field
// which are exposed in the Remote Interface as well
这个设计模式虽然很简单,但是却有很多缺点,比如,对每一个字段的访问都会导致对get()和set()方法的一次远程调用。而远程过程调用(RPCs)是非常耗费资源的,并且,对于在实际中通常要求的组合的访问会导致一系列的远程调用。可以说,这个模式在实际中可用性很差。上面展示的设计模式可以作为其他设计模式的基础,比如RAD,原型设计,测试等。这时,那个代表雇员的Employee Entity Bean并没有展示出在雇员和公司之间有何关系。
:
为了避免设计模式1的缺点,我们介绍一下封装entity bean值域的value objec的概念。value object,用某些语言的术语来说,就是一个结构类型,因为他们
和corba的结构类型非常类似。
value Object code snippet for Company
public class CompanyStruct implements
java.io.Serializable {
public Integer comId; //Primary Key
public String comName;
public String comDescription;
public java.sql.Timestamp mutationDate;
}
value Object code snippet for Employee
public class EmployeeStruct implements
java.io.Serializable {
public Integer empId; //Primary Key
public Integer comId; //Foreign Key
public String empFirstName; public String empLastName;
public java.sql.Timestamp mutationDate;
}
现在,公司和雇员的entity bean可以把上面的一个结构类型作为ejbCreate()的一个参数。由于这个结构封装了entity的所有字段的值,entity bean只需要一个getdata()和setdata()方法就可以对所有的字段进行操作。
Code snippet for an Entity Bean’s create()
public Integer ejbCreate(CompanyStruct struct) throws
CreateException {
this.comId = struct.comId;
this.comName = struct.comName;
this.comDescription = struct.comDescription;
this.mutationDate = struct.mutationDate;
return null;
}
Code snippet for an Entity Bean’s getData()
public CompanyStruct getData() {
CompanyStruct result = new CompanyStruct();
result.comId = this.comId;
result.comName = this.comName;
result.comDescription = this.comDescription; result.mutationDate = this.mutationDate;
return result;
}
Code snippet for an Entity Bean’s setData()
public void setData(CompanyStruct struct) {
this.comName = struct.comName;
this.comDescription = struct.comDescription;
this.mutationDate = struct.mutationDate;;
}
跟设计模式1中使用单独的get()和set()方法去操作特定字段不同,在设计模式2中,我们避免这种情况而只需要进行一次远程调用就可以了。现在,只有一个事务通过一次远程调用就操作了所有的数据。这样,我们就避免了设计模式1的大部分缺点,除了建立bean之间的关系外。虽然setdata()方法可以对所有字段赋值,但是,borland appserver提供了一种智能更新的特性,只有被修改过的字段才会被重新写入数据库,如果没有字段被修改,那么ejbStore()方法将会被跳过。borland程序员开发指南(EJB)有更详细的描述。同样,在entity bean和struct之间存在这重复的代码,比如同样的字段声明。这意味着任何数据库表结构的修改都会导致entity beabn和struct的改变,这使得同步entity和struct变得困难起来。
就是在ebCreate()方法中调用setddata()方法,这可以消除一些冗余的代码。
Code snippet for an Entity Bean’s create()
public Integer ejbCreate(CompanyStruct struct) throws
CreateException {
this.comId = struct.comId; //set the primary key
setData(struct);//this removes some redundant code
return null;
}
:
在设计模式2中我们看到,在entity bean和struct之间有很多重复的代码比如同样的字段声明(对应数据库中的表列)。如果让entity bean从结构继承下来就可以避免冗余的代码。但是这种设计,仍然不能显示beans之间的联系。
Code snippet for Company Entity Bean
public class CompanyBean extends CompanyStruct
{
implements EntityBean
EntityContext entityContext;
//all fields in CompanyStruct are available for CMP
public Integer ejbCreate(CompanyStruct Struct)
throws CreateException
{
this.comId = struct.comId; //set the primary key
setData(struct);//this removes some redundant code
return null;
}
}
其余的代码比如getdata()和setdata()方法的实现和设计模式2中是完全一样的。