Container-Managed Persistence Examples一個container-managed的實體bean帶給開發人員很多好處。首先,EJB容器管理所有數據庫的存儲與同步指令;其次容器管理實體bean之間的關系。由於這些服務的存在,你不用去編寫數據庫邏輯,你所要做的只是在配置描述裡面描述這些信息,這樣不僅可以節約時間而且使得bean可以在多種數據庫服務器使用。 這章我們的實例是一個container-managed的實體bean。這個應用的名字叫RosterApp。 RosterApp總攬:這個RosterApp應用程序維持在一些體育運動聯盟的球員的名單以及球隊的名單。這個應用程序有5個組件。RosterAppClIEnt組件是一個客戶端組件,他通過RosterEJB會話bean的romote接口訪問RosterEJB。 RosterEJB訪問3個實體bean-PlayerEJB, TeamEJB, and LeagueEJB,這些訪問是通過3個實體bean的local接口。 這些實體bean采用CMP方式,TeamEJB和PlayerEJB的關系是多對多的雙向的, LeagueEJB和TeamEJB的關系也是雙向的,但是是一對多的關系。 編寫PlayerEJB 這個實體bean代表一個存儲在數據庫的球員,像所有的CMP實體bean,PlayEJB需要如下的代碼: 1 Entity bean class (PlayerBean) 2 Local home interface (LocalPlayerHome) 3 Local interface (LocalPlayer) Entity bean class 為了實現CMP,這個實體bean的類必須是public和abstract的。同時也必須實現以下的條件: 1 EntityBean interface 2 0個或者多個ejbCreate和ejbPostCreate方法 3 get和set抽象方法。 4 一些抽象的select方法 5 home方法 6 商業方法這個bean不能實現的方法: 1 finder方法 2 finalize方法 Access方法一個CMP實體bean有persistent和relationship,這些是虛擬的,所以你不用把他們定義為實例變量。你所作的只是在配置時描述他。但是你需要定義get和set方法。容器自動管理數據庫的存儲和同步,配置中這些persistent需要被容器維持: 1 playerId (primary key) 2 name 3 position 4 salary 我們需要這些方法訪問這些:
public abstract String getPlayerId();
public abstract void setPlayerId(String id);
public abstract String getName();
public abstract void setName(String name);
public abstract String getPosition();
public abstract void setPosition(String position);
public abstract double getSalary();
public abstract void setSalary(double salary);
這些方法的名字以get或者set開頭,後面跟著persistent的名字。 這和JeanBean是一樣的。 同時我們需要Access方法訪問Relationship在這個應用程序中,因為一個球員可以在多個球隊效力,所以一個PlayerEJB對象可以和很多TeamEJB相關。我們定義這個Relationship名字為teams,接下來我們需要定義這些Access方法。
public abstract Collection getTeams();
public abstract void setTeams(Collection teams);
Select方法一個Select方法和一個Finder方法類似: 1 一個Select可以放回一個local或者remote接口(或者一個集合) 2 一個Select需要一個query連接數據庫 3 需要自己在配置中定義一個EJB QL 4 bean類不需要實現這個方法但是2者也有不同的地方: 1 一個select方法可以返回相關聯的bean一個persistent(或者集合),一個finder只能返回local或者remote接口。 2 由於select方法不在local或者remote接口,一個select方法不能直接被客戶調用,只能被這個bean的內部方法調用。通常被一個商業方法調用。這個程序中定義了如下的select方法:
public abstract Collection ejbSelectLeagues(LocalPlayer player)
throws FinderException;
public abstract Collection ejbSelectSports(LocalPlayer player)
throws FinderException;
select方法名必須滿足: 1 前綴必須是ejbSelect 2 Access控制訪問是public的 3 abstract 4 拋出的exception必須包含Javax.ejb.FinderException 商業方法由於select方法不能被客戶直接調通,所以將他們包含在商業方法中:
public Collection getLeagues() throws FinderException {
LocalPlayer player = (team.LocalPlayer)context.getEJBLocalObject();
return ejbSelectLeagues(player);
}
public Collection getSports() throws FinderException {
LocalPlayer player = (team.LocalPlayer)context.getEJBLocalObject();
return ejbSelectSports(player);
}
實體bean方法由於是CMP,所以bean的生命周期方法基本不用實現 ejbCreate方法:
public String ejbCreate (String id, String name, String position, double salary) throws CreateException {
setPlayerId(id);
setName(name);
setPosition(position);
setSalary(salary);
return null;
}
譯者注:注意return null除非debug的需要,ejbRemove方法一般都是空的。當容器調用這個方法後,容器刪除數據庫中的紀錄。 ejbPostCreate方法和ejbCreate方法的參數和返回類型一樣,如果你想建立一個關系,你應該把代碼寫在ejbPostCreate方法中。容器會自動管理同步,存儲等數據庫操作,這些通過ejbLoad和ejbStore方法完成。 local home interface: 這裡定義了creat,finder和其他一些home方法。
package team;
import java.util.*;
import Javax.ejb.*;
public interface LocalPlayerHome extends EJBLocalHome {
public LocalPlayer create (String id, String name, String position, double salary)
throws CreateException;
public LocalPlayer findByPrimaryKey (String id)
throws FinderException;
public Collection findByPosition(String position)
throws FinderException;
...
public Collection findByLeague(LocalLeague league)
throws FinderException;
...
}
loca interface: 這裡定義了一些商業方法,這些方法有bean實現,同時也定義了get和set方法,set方法不應該被暴露出來。
package team;
import java.util.*;
import Javax.ejb.*;
public interface LocalPlayer extends EJBLocalObject {
public String getPlayerId();
public String getName();
public String getPosition();
public double getSalary();
public Collection getTeams();
public Collection getLeagues() throws FinderException;
public Collection getSports() throws FinderException;
}