我作为BEA的顾问已经成功地帮助客户在各种版本的WebLogic Server (WLS)上设计并部署了应用程序BEA从EJB 已经开始支持容器管理(CMP)的实体beans并且已有一些客户在使用它们可不幸的是一些客户在不理解实体bean的情况下就使用上了它们而另一些客户一听说它会对性能有某些约束就完全从他们的结构/设计选择上排除使用实体beans 当面对系统分析师的询问我究竟何时应该考虑去使用CMP方式的实体beans呢?的时候我很难解释为什么要使用CMP形式的实体beans实体beans的优势体现在两方面高速缓存和对象-关系的映射两者在先前的版本中都勉强的被实现但EJB 拯救了这种情况WLS 在EJB 规范上的附加功能弥补了在使用实体beans和使用无状态会话beans之间在性能方面的差距说明无状态会话bean是通过DAO和JDBC访问数据库的在某些情况下实体bean甚至比无状态会话bean执行的快当使用JDBC时强烈建议开发者使用容器管理的事务 早期版本的问题 一些在过去使用实体beans的客户不得不重新设计和使用JDBC因为他们的系统太慢以至于无法满足服务缓慢的原因在于 没有高速缓存 每个事务为了加载实体bean都访问数据库客户在使用实体bean时所期望的承诺之一是缓存而对规则实体beans来说在集群环境中是没有缓存可以使用的 单一表支持 (OR 映射过分简单化) 客户也期望对象-关系映射可以由实体bean完成但是由容器提供映射功能过分简单了 每个虚拟机(VM)只能有该实体bean的单一实例由于WebLogic 和更低的版本只支持互斥锁所有对实体bean的调用都是串行化的这样会引起系统瓶颈甚至是对只读beans 互斥锁 当一些beans在使用事件而另一些没使用的时候死锁发生的可能性很高 单一setX调用这引起整个实体bean都被写进数据库在EJB 规范前容器对于判断哪些内容发生了改变哪些没有发生改变是没有办法的这意味着在ejbStore时所有的属性都要更新 装载 装载实体bean使所有的数据成员都装进内存只需要几个的时候 无动态查询 写了一个新的查询时EJB必须被重新部署 查询 查询会实例化大量的实体beans消耗内存并且降低系统性能 WLS 的特征 WLS 实现了在EJB 中提供的丰富的对象-关系映射规范在优化读写数据库方面EJB 也为容器提供了更丰富的便利下面说明了开发者在WLS 中设计实体beans方面所拥有的丰富和灵活的特征 容器管理的关系 实体beans可以关联其他的beans这些关系可以是双向的或是单向的WLS支持三种类型的关系映射由WebLogic CMP管理一对一一对多多对多 一个实体bean的多表映射多表的支持允许一个符合EJB 特征的CMP beans的实现器将一个EJB 映射为一个据库中的多DBMS表 调优EJB的写操作当调用ejbStore时只更新写进数据库的字段而不是把所有字段都写进数据库 使用字段组调优读操作在ejbLoad容器只装载fieldgroup中的字段而不是装载实体bean的所有字段 关系的缓存 这个特征提高实体bean的性能通过在某一个联合查询(非多重条件查询)中缓存并装载相关的beans 实体beans可以返回ResultSets(记录集)WLS 支持ejbSelect()查询它在javasqlResultSet的表单中返回多列的查询结果 对不同种类的实体beans的应用级的缓存 代替对每个实体bean分散的缓存这个特征可以使多个实体beans 在一个EAR中共享一个单一运行时的缓存 动态查询 EJB 规范强制用户在部署描述符中编写查询代码通过采用动态查询新的查询可以通过程序被构造和执行而不用重新部署beans Readmostly设计模式在现实世界中大部分应用程序的% 为读取而%为更新实体bean可以被写成模拟数据并且可以部署为只读实体bean和规范的实体bean通过这种方法想要读取数据的用户与只读实体bean交互而想要修改数据的用户与规则的实体bean交互当修改发生时容器使所有的只读实体bean失效当数据访问再次发生时迫使容器调用ejbLoad 其他有用的特征包括自动生成主键支持级联删除支持EJB QL(Query Language查询语言)ejbSelect方法以及下面所描述的并行策略 并行策略 并行策略定义一个实体bean创建多少实例为了维持事务的完整性谁来实现同步以及在实体bean中的数据模型存取模式恰当的并行策略可以使实体bean在性能上产生极大的不同 互斥性对于每个VM实体bean容器只产生一个实例所有实体bean的调用都作为使用容器锁的实体bean来串行化这绝不被推荐使用 数据库容器延期对数据库的锁定并且每个事务都有它自己实体bean的拷贝ejbLoad 和 ejbStore 在各自事务的开始和结束时被调用 只读实体beans 数据库和容器都不支持任何的锁每个事务得到它自己的实体bean的拷贝一个叫做的可配置参数用于控制实体bean调用ejbLoad方法EjbStore在实体bean上永远不会被调用客户端仍然可以在实体bean上进行创建移除和更新操作创建和移除操作会成功而由于不调用ejbStore更新操作将不会修改数据库在只读实体bean上不调用CUD(create update delete)方法是程序员的责任只读实体bean对于分布式缓存问题是最好的解决方法 开放式的实体beans 容器延期对数据库的锁定但是该锁在事务期间不予以保留其基本思想是容器在提交前检查修改了的数据并且如果其他人也修改了数据时将该操作回滚如果你想有比TX_READ_COMMITTED更高的一致性而不需要达到TX_ SERIALIZABLE那么高的一致性时这样做是很有用的如果你能忍受短时间读取陈旧的数据而又想完成一些update操作的事务完整性时你可以使用它这里有四个选项可用于检查optimistic式沖突 . 检查读取的列 . 检查修改的列 . 检查时间信息列 . 检查版本信息列 选项和是不被推荐的因为为适应这个并行策略表的结构需要改变 同样对于开放式并行策略你可以配置在事务为true和false期间你是否需要缓存对在事务期间设置为false的缓存将在每个事务开始的时候调用ejbLoad 比较 对于CMP总要有附加处理过程的这是由于在EJB容器以及容器层上(合成码)有一个集成该容器层用于处理事务安全池态生命周期管理failover缓存和关系这里CMP(由设计或由规范)必须做一些内部操作(ejbLoad ejbStore ejbActivate ejbPassivate)就像反对JDBC逻辑而由开发者自己手写编程容器基础结构的好处是优化并生成数据库访问加速开发以及简化代码维护 在我见过的基准上除非数据是被缓存了的 [stateless session bean + DAO (做 JDBC访问)] 执行比实体bean执行快% 什么时候使用什么 实体bean不能用来取代编写JDBC如果你的对象-关系模型不是极度复杂(包括许多连接等等)和灵活并且对于工程代码的维护比速度更重要时可以使用实体beans 使用JDBC于简单的原子级别绑定的更新使存储过程和触发器相结合并处理大量的ResultSets(记录集) WebLogic附加的功能例如readmostly设计模式和开放式缓存cachebetweentransactions设置成true是两种设计选择它使实体beans成为吸引人的选择它们都是BEA所特有的属性在WebLogic特殊部署描述符中指定的当转移到另一个适用JEE的应用服务器上时无需代码变更对于应用来说通过使用开放式缓存并行策略可以在短时间读取旧的数据 对于大多数在读取而少数时候更新的用例使用readmostly设计模式这种设计模式也有缺点就是用户会读取到过时的数据对于一些用户完全不应读取过时的数据的情况他们可以从读写bean读取 CMP实体beans的只读实体beans的特征将在以后发布的EJB规范版本中有所提及使用只读实体beans来实现一个可以周期性更新的分布式缓存 结论 现实世界中大多数的应用程序的读操作比写操作多很多现实中readmostly模式对两种情况来说都将是最好的方法它提供简单的开发和灵活的部署并且对于存取数据提供卓越的性能特性只有当数据被修改时才会有的额外开销cachebetweentransactions设置成true的开放式的并行可以比JDBC还快编写最优化的SQL对于正规的Java程序员来说很难所以不要忽略实体beans的价值并决定它们是否最适合 实体Beans的例子 提供的示例在BEAHOME/samples/server/src/ejb子目录下 论证关系的示例参看BEAHOME/samples/ server/src/ejb/relationships/bands目录 论证多表映射的例子参看BEAHOME/ samples/server/src/ejb/multitable 目录 使用数据库并行选项在weblogicejbjarxml中指明Database 使用只读并行选项在weblogicejbjarxml中指明Readonly 使用开放式并行cachebetweentransactions并且检查改进的选项在weblogicejb jarxml中指明Optimistic True并且在weblogiccmprdbms jarxml中指明Modified 实现readmostly设计模式注册bean的实现就像两个EJBs一个作为只读另一个作为可读写的并且在weblogicejb jarxml中ejbname是只读实体bean名字处添加ejbname |