分享
 
 
 

Seven Rules for Optimizing Entity Beans

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

优化Entity Beans的七条原则 (自已翻译的老文章 :P )

Entity beans提供了一个清晰的模型,它描述了应用当中持久的商业对象和这些对象的设计构思。在对象模型中,简单的Java对象通常用最直接了当的方法来描述,但这没有包括在商业对象中常常需要用到的事务持续管理功能。Entity Beans不仅允许在一个对象模型中有相同类型商业对象的建模和考虑,而且也在bean和container服务后面隐藏所有复杂性的同时封装了持久机制。这将允许应用程序以Java对象的形式去操作这些Beans。对于任何调用代码,持久的形式和持久机制都是隐藏了的。Entity beans允许container创造性的进行最佳化持久,在遵守数据存储的开放和灵活的同时,没想到决定部署时间。

以EJB为基础的项目开发,大量使用了面向对象方法和entity bean,Sun的工程师已经掌握在真实世界中使用entity beans。这篇文章详细闸述了如下的开发经验:

·探究不同的优化方法

·提供关于达到最佳性能和灵活性的建议和标准

·讨论如何避免一些已知的危险

Use Container-Managed Persistence When You Can(尽可能的使用CMP)

不要认为CMP只是用来以写少量代码来减轻工作的方法,它也是container最佳化EJB的方法,并让container自动产生的数据库存取代码。Container通过访问bean的内存缓冲区实现监控缓冲区的任何变化(也就是监控bean的变化)。在一个事务提交之前保存缓冲区到数据库,避免了缓冲区在没有任何改变时对其进行存储操作,也就避免了不必要的数据库调用而产生的昂贵开销。

另一个优化的建议是关于find方法的调用。查找一个entity bean通常包括两个数据库操作:

·查找数据库中的一条记录并取得它的primary key.

·取得这条记录将其放到缓冲中

CMP允许优化这两个数据库操作,使它们成为一个操作,无论何时都是有意义的,它可以在一个数据库调用中同时取得primary key和记录数据。

Write Code that Supports Both Bean- and Container-Managed Persistence(编写对BMP和CMP都支持的代码)

很多案例中,EJB的作者没有控制到EJB在部署时,container是否将支持CMP。同样,部署人员最终可能选择在container中使用BMP方式。你必须找到一个实现方法,让beans在允许BMP部署时又不会因为需要支持更多可能的CMP优化机制时发生混乱。一个方便的方法可以实现这个目标,就是将纯商业逻辑从持续机制中分隔出来。商业逻辑的实现在你的CMP类中,它能在选择CMP方式时单独部署。这样,将持续代码放到BMP类中,将其从CMP的类中进行继承。这样就做到了CMP超类中包含所有的商业逻辑,而BMP子类中则包含了数据库存取代码,如图1。

Figure 1: Separation between CMP and BMP

这个模型非常容易实现,但仍使灵活性受到了抑制:

它不可能从implementation classes中继承。

因为这样做意味着子类必须从CMP和BMP这两个超类中同时直接继承。另外,BMP子类将不得不直接成为CMP的实现。这就导致了多重类继承,如图2,Java编程中是不允许多重继承的。

Figure 2: Multiple inheritance not supported in Java

没有简便的方法来支持变化的持续执行。

如果可以的话,这将非常有用,如为不同的数据库提供商或不同类型的数据库执行包含数据库特殊代码。(如关系型、对象型,和其他一些旧类别的数据库)

要解决这些问题,你需要改变当前BMP的类模型,委托BMP类中的所有的持续代码给一个辅助类,并且去除BMP类中的框架。辅助类的类型被称为DAO(Data Access Object数据存取对象)。你能让DAO的interface中提供多个DAO的子类,这样就允许正确的DAO子类被实例化。如图3.这里有很多种方法来选择和实例化正确的DAO子类,比如,可以通过读取环境入口或者通过了解数据库类型来选择最合适的子类。

Figure 3: Delegation and allowing for alternate DAO implementations

使用这个类型,CMP实现和包含实现的DAO都能轻易的进行扩展(继承);可以从BMP的类中继承任何东西!因为这些BMP的类包含了看起来几乎相同的所有entity bean中授权的基础代码,并且实例代码会选择正确的DAO对象,你只需要做一点点的修改,就能方便的将一个bean复制成一个新的bean。同样,你最终可以做到用一个工具来自动生成它们!

当通过继承一个entity bean来重用另外一个bean所提供的逻辑时,这不会使EJB1.1规范允许通过扩展entity的类型来扩展home 接口。Finders和create的调用在理论上始终是远程调用。生成的残余代码(stubs?)将永远不会描述为一个子类型,尽管逻辑上可以(比如,把它们作为一个factory方法)。这阻止了在参照EJB1.1规范的EJB实现中使用很多有用的设计模式。

Minimize Database Access in ejbStores(在ejbStores中最小化数据库存取)

当使用CMP时,bean绝对不能控制ejbStore,它将所有的优化操作交给了container。由container来提供的CMP优化是快速container和慢速container区别的要素。

只要bean使用BMP来部署,对操作缓冲区变化标志来说是非常有用的。缓冲区的所有改变将可以通过ejbStore中设定这个标志来判断。如果标志没有被修改,则意味着缓冲区没有被改变,ejbStore正就这样跳开了所有数据库存取的开销。这个决窍对于这些经常进行查询而很少进行更新的beans来说尤其有用的。它们通常是很多应用的大部分组成(如表查找)。

这个方法有个需要注意之处。当这个标志因数据库存取而被修改时,它将适合放在BMP方式的代码当中。在以前面所说到的模式实现时,将这个标志放在BMP代码框架上或者放在DAO中。因为DAO在调用商业方法时从未被调用,它们不是标志需要放的正确位置,应该将标志放到BMP框架代码中。这个天性使得BMP代码更加复杂难懂,因为商业方法需要委托超类进行重载。

理论上,EJB的作者将不会不得不处理系统级的问题,如缓冲区操作。不幸的是,EJB1.1使BMP不能提供任何为优化所做的折衷的方法,因此bean的作者仍不得不手工设置数据库改变标志。

Always Cache References Obtained from lookups and find Calls(将lookups和find调用取得的References缓存)

Reference Caching对于entity beans和session beans都是有用的。JNDI要寻找EJB 资源,如DataSources,bean References,或者连环境入口也能公平的开销?,并且简单的做到避免进行多余的lookup。要解决这个问题,需要:

·将这些references定义成实例变量

·在setEntityContext中找到它们(session beans中是setSesssionContext方法)

SetEntityContext方法只是在实例化bean时调用一次,因此在此时寻找所有需要的references不会有真正的开销。避免在任何其他方法中寻找references,尤其是对数据库进行存取的方法,ejbLoad和ejbStore。一些方法会被频繁地调用,导致大量的时间花费在无意义的lookup调用上。

在调用一些entity beans的finders方法时这也是非常重要的,当这些调用可能适合或不适合bean初始化回调时(如setEntityContext),就可以缓存由finds方法产生的references结果,这在任何时候都是适用的。由finder方法的多余调用产生的开销是非常高的。如果reference只对当前entity有效,你需要在实例描述其他实体(entites)开始重新活动之前清除references。这需要在ejbActivate方法中完成。

Always Prepare Your SQL Statements(总是使用Prepare的SQL语句)

这种优化方法对于使用SQL存取关系数据库的所有代码都有用。目前大多数的EJB使用关系数据库实现,这个标准对于bean作者不得不编写数据库存取代码进行EJB开发也是非常有用的。

对于每一条被数据库处理的SQL语句,数据库都需要在执行这条语句之前对其进行编译。好的关系数据库,无论如何,能够缓冲语句和它的编译形式,并将新语句与相对于从缓冲中取得的语句编译形式进行匹配。无论如何,为了使用这种优化方法,新的语句必须正确的匹配旧的语句。

·Non-prepared 语句:对于non-prepared语句,数据和语句本身是在同一个字符串中传送,尽管语句在后来的调用中看起来是一样的,但数据并不一样,从而不能被优化。

·Prepared语句:对于prepared语句,只传送了没有数据的语句到数据库,而从缓存中取得形式(form)

当你在使用语句时,数据传送到语句,语句开始执行。通常,语句在准备(prepare)时被编译,但后继的prepares已经匹配了缓存中的语句,而且不需要重新编译。这项技术提升了非常高的语句(statement) cache命中率,最小化了语句(statement)的编译总数。对于小型数据库的存取,它能减少90%以上的语句执行时间!

Close all Statements Properly(关闭所有Statements)

当在BMP实现中处理数据库存取代码时,绝对不要在数据库存取调用之后打开语句(statement)。每打开一个statement相应的在数据库中打开一个游标。(当垃圾收集器终于要求打开statement,并在垃圾收集时关闭它时,你不能控制垃圾收集器打开的时间。不要通过System.gc的方法强迫垃圾收集器)不关闭Statement将导致数据库过多的打开游标,消耗数据库资源的操作相反可以利用它来改进数据库的性能。

同样,确认在关闭statements时完全捕捉所有例外。在一个闭环的statement中的例外必须不影响到其他statements,使其被忽略和只有打开没有关闭。

Avoid Deadlocks(避免死锁)

应用程序代码不可以直接控制ejbStore(或者等价于CMP)何时被调用。这由Container决定什么时候调用,通常在事务最后被调用。

如果多个entity beans或多个实体(eitities)涉及到一个事务,ejbStore被调用的顺序是不可定义的。这也意味着用户不能控制描述这些实体(entities)的数据库记录的存取/锁定顺序。当多个表/行涉及到一个混和锁定命令非常有可能导致死锁。

从完美的、理想的一面来看,container能够控制EJB中的存取和锁定,也就能够解决死锁,并且消除了开发者/部署者的诸多疑虑。不幸的是,当前几乎没有任何有效的商业性质的应用程序服务器能够在处理数据库锁的方面做得很好,只能将复杂entity bean部署中死锁的问题留给部署者。

可应用的标准,至少在写这篇文章时,假设container将以相同顺序调用beans中的数据库存取调用,这个beans的事务方法是事务中第一个被存取的部分。更清楚的认识请思考以下的例子:假设entity bean EB1有一个事务方法 m1,entity bean EB2有一个事务方法 m2。如果在一个事务当中,EB1.m1在EB2.m2前被调用,也可假设EB1.ejbLoad在EB2.ejbLoad之前被调用,并且EB1.ejbStore也在EB2.ejbStore之前被调用。这意味这个实体或数据库记录描述的EB1是在EB2之前被锁定的。要避免死锁,确认在贯穿整个应用程序的任何事务当中EB1永远在EB2之前被调用。

当应用程序服务器变得越来越聪明且知道如何命令数据库存取时,EJB作者和部署者将可能放心bean的存取顺序了。无论如何,代码要严格的处理调用顺序,象例子中提供的,要做到像今天这样能继续在未来的服务器上运行。

Going Forward

利用这些标准,在实体-加强器(entity-intensive)开发时和部署时,对增加beans的性能和灵活性有另人瞩目的帮助,允许在最小化它们在container和底层系统的载入时,让它们去适应不同的持久的存储类型。这将让部署者灵活的选择大多数相配的部署基础结构,并且允许beans有效的使用基础结构所提供的功能。换句话说 – 一次编写随处运行,高效。

For More Information

Enterprise JavaBeans downloads and specifications

jGuru's Enterprise JavaBean Fundamental short course

Recent Java Developer articles on Enterprise JavaBeans

The ECperf workload

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有