什么是实体?(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 自动为您生成库表
本章讲述了内容 Entity bean 持久的对象有更长的生命 (相对) Entity bean 直接反应到数据库中--它们可以跨服务器停机而存在 Entity bean 可以找到 Entity bean 属性可以标注为 container-managed 或者作为主键的一部分 在 "Finder Helper" 中可以指定 "Where" 语句