什麼是一個實體(Entity) Bean
一個持久對象
通常它是被當成一樣"東西",或者會長期存在的
BankAccount
Employee
Order
不僅僅只是數據--狀態和行為,與常規對象一樣
在數據庫中的實體 Bean
一個實體 bean 直接映射到數據庫中的一行數據
ID LASTNM MGR DEPT SALARY
... ... ... ... ...
42 "Joe" Smith 0 55000.0
97 "Bob" Jones 42 40000.0
102 "Mary" Chen 987 63000.0
... ... ... ... ...
Employee
id: int
first: string
last: string
Salary: double
Managerld: int
Dpartmentld: int
Entity Bean 和 Persistence
根據規范定義,實體 Bean 一旦被創建後就存在
它們被直接寫到數據庫中
可以不受任何服務器的宕機影響
Create 方法必需提供足夠的信息將 Bean 保存到數據庫中
實體 Bean 與 會話 Bean 的區別
實體 Bean
持久對象; 不受服務器宕機影響
有一個主鍵; 可以被搜索到
可以被共享
必需被顯式刪除
會話 Bean
不是持久的; 受服務器宕機影響
不可以被搜索
通常一個用戶使用一個 bean
過一段非活動期後將被自動回收
Aside: 什麼是一個主鍵?
(一個或多個)域可以唯一地區別一行數據/一個 bean--用來查找和更新數據/對象
在數據/對象的生命周期中是不變的--主鍵是基於不變的數據
主鍵通常是生成的而不是基於"活躍"的數據
SSN 顯然適合於作為一個主鍵
就算錯誤選擇的主鍵不能再被修改
Aside: 什麼是一個關系型數據庫?
數據庫: 一組數據集合可以被檢索和查找--一個關系型數據庫維持不同行數據間的關系
數據被組織成表格--外鍵(Foreign Key)用來映射關系、Structured Query Language (SQL) 用來操作數據庫
讀 (select), 寫 (insert, update), 刪除 (delete)
同步訪問的控制
容器管理同步訪問--線程獲得對 Bean 的獨有訪問、即 Bean 的每個方法是 synchronized
警告: 當心死鎖!
Bean 本身也是客戶!
Client 1 有對 Bean 1 的獨有鎖
Client 2 有對 Bean 2 的獨有鎖
Bean 1 必需等待 Client 2 的結束
Bean 2 必需等待 Client 1 的結束
沒有任何一方得到鎖!
實體 Bean 有主鍵
主鍵用來唯一地區別 bean--類似於數據庫主鍵的概念
主鍵類:必需反映 bean 類的"關鍵"狀態、必需提供 equals(...) 和 hashCode() 方法
主鍵可能由多個域組成
...
Employee employee
= employeeHome.findByPrimaryKey(new EmployeeKey(42));
...
Create 方法
Home 定義了一個或多個 "create" 方法--在創建後,Bean 必需馬上被寫到數據庫
EmployeeHome method
Employee create(int arg1, String arg2, String arg3)
throws CreateException, RemoteException
EmployeeBean method
public void ejbCreate(int argId, String first, String last)
throws CreateException, RemoteException {
id = argId;
setFirst(first);
setLast(last);
setManagerId(0);
setDepartmentId(0);
}
Post-Create
對每個 ejbCreate 方法必需有一個 ejbPostCreate--有相同的參數
容器將:
調用 ejbCreate(...) 方法, 它將返回所創建實體的一個主鍵
創建對應該主鍵的一個 EJB 對象引用
調用 ejbPostCreate(...) 方法通知實例來完全初始化它本身
public void ejbPostCreate(int argId, String first, String last)
throws CreateException, RemoteException {
}
Finder 方法
Bean home 接口定義了 "ejbFind" 方法---通過 VAJ 的 Persistence Lay, 容器提供一個實現
方法將返回:---單個結果的 Remote 接口、多個結果的 Enumeration
Must be provided
Employee findByPrimaryKey(EmployeeKey key)
throws RemoteException, FinderException;
Employee findById(int id)
throws RemoteException, FinderException;
Enumeration findByLastLike(String pattern)
throws RemoteException, FinderException;
Enumeration findBySalaryRange(double low, double high)
throws RemoteException, FinderException;
生命周期
Container-Managed Persistence
容器管理 Bean 的生命周期--何時創建、載入、存儲和刪除
容器提供存儲機制--如何創建、載入、存儲和刪除
Bean 部屬人員定義 Bean 和數據庫之間的映射
VisualAge 和 CMP
VisualAge 提供工具來:
從一個數據庫模式(schema)來創建 Bean
從實體 Bean來創建數據庫模式
Meet in the middle: 利用現有的 Bean 和模式
構建一個實體 Bean
容器管理的域...
當 Bean 被創建時可以定義域
中間的屏面可以切換 Bean 類和域---使用這個功能來定義額外的容器管理的域
模式(Schema)和映射(Map)
模式(Schema)
描述數據庫模式
將原始數據轉換成 Java 類型
將 Java 類型轉換成原始數據
映射(Map)
定義如何從模式中的一行數據構造對象
定義如何從一個對象構造數據行
生成數據庫模式
添加一個模式和映射--"EJB > Add > Schema and Map from EJB Group"
導出模式導數據庫--打開 Schema Browser
Aside: JDBC
JDBC 驅動程序
描述 Java 和一個數據庫之間的接口
作為一個 Java 類而實現
一般由數據庫廠商提供
JDBC URL
描述數據庫位置(如何查找)
部分格式是各廠商定義的
生成庫表
大多數 DBA 嘲笑數據庫表的自動生成--有個理由: 高效的庫表設計需要精心考慮
生成的庫表足以供測試使用
CMP 提供了在您的 Bean 和存儲機制間的屏蔽--在測試時使用自動生成庫表, 部屬時另外考慮
"FinderHelper" 類
為每個 finder 方法定義 "where" 語句
"?" 被參數值替換(按次序)
WebSphere 獨有
Employee findById(int id) throws ...
Enumeration findAll() ...
Enumeration findByLastLike(String pattern) ...
Enumeration findBySalaryRange(double low, double high) ..
public interface EmployeeBeanFinderHelper {
public static final String findByIdWhereClause = "ID = ?";
public static final String findAllWhereClause = "1 = 1";
public static final String findByLastLikeWhereClause
= "LAST LIKE ?";
public static final String findBySalaryRangeWhereClause
= "SALARY > ? and SALARY < ?";
}
Aside: 設置 DB2
VAJ 的工作區必需能夠訪問 DB2 驅動程序--使用 "Window > Options..."
創建一個數據庫
使用 DB2 的控制台來構建一個數據庫
參考 Smartguide 中的指示
VisualAge 為您自動生成庫表 .