分享
 
 
 

Coarse Grained BMP beans with Dependent Value Objects

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

Coarse Grained BMP beans with Dependent Value Objects

is a draft pattern from the upcoming sequel of Mastering Enterprise Java Beans. The pattern describes how to properly implement the equivalent of Dependent Objects in BMP, and provides a fully resuable implementation as an example. The pattern does not describe the motivation for dependent objects, that is a separate pattern and you can learn more about it by reading the EJB 2.0 specs or Sun's ejb-interest archives.

Coarse Grained BMP beans with Dependent Value Objects

By Floyd Marinescu, Senior Architect, The Middleware Company.

Please email comments/suggestions to: floyd@middleware-company.com.

Performance and efficiency concerns require a standard way to build coarse-grained entity beans using BMP as well as CMP.

Dependent objects provide an automatic way to build coarse-grained entity beans for CMP entity beans, but the EJB 2.0 specification doesn’t provide an equivalent mechanism for BMP entity beans.

* * *

Building your entity beans to be coarse-grained is a common performance optimization. It allows modeling the business objects with plain java classes rather than as entity beans, reducing the inter-remote object communication and transactional overhead associated with entity beans. These plain classes typically have a life cycle dependent on a parent entity bean, do not have a distinct identity of their own and do not need to be referenced remotely by a client. For CMP, these objects are called dependent objects, and EJB 2.0 defines a standard way to define CMP dependent objects, leaving the complex task of persisting them to the underlying application server.

Unfortunately, BMP entity bean developers cannot leverage dependent objects, they are a CMP construct only. However, BMP developers should still be able to create coarse-grained entity beans,

Therefore:

BMP developers should model dependent business data in plain java classes called Dependent Value Objects. Dependent Value Objects are stored inside your entity beans and are created, modified and removed by your entity beans. Unlike dependent objects with CMP, BMP developers must explicitly write the persistence code of dependent value objects.

Dependent Value Objects are similar to Value Objects in that they are plain java classes and are transportable over the network (this is one advantage over CMP dependent objects, which cannot be accessed by clients). Unlike Value Objects, Dependent Value Objects are persistent objects whose life cycle is managed by an entity bean, whereas Value Objects only exist to transport data across the network in bulk, and are typically discarded once data has been read.

An entity bean can store dependent value objects in a one to one, or one to many fashion. For example, consider a Resume. A Resume entity bean would only require one Address dependent value object, whereas it would require multiple Job Entry objects, which could be stored in a Collection inside the Resume entity bean, as in figure 1.

Figure 1: ResumeBean class diagram with Address and Job Entry Dependents

Implementing dependent value objects with BMP is not trivial. A good implementation will feature:

Dependent value objects that map to tables in a database

Immutable dependent value objects

Lazy loading of dependent value objects

Intelligent lifecycle management (caching updates until ejbStore, only storing new or modified dependent value objects, etc)

Partitioning of persistence logic from business logic

One of the easiest ways to persist dependent value objects is to simply serialize them to a SQL BLOB column in the table which your entity bean maps to. If dealing with a collection of dependent value objects, the whole collection could be serialized into this column. A better alternative is to persist your dependent value objects to separate tables, using JDBC to map your objects in an attribute-per-column manner. Persisting your dependent value objects in this manner will allow them to be accessible to sql searches and allow you to perform reporting and maintenance directly on the database (you can’t do this if they are stored as blobs). From our Resume example, our Resume entity bean maps to a resumes table in the database, whereas our Address dependent value object maps to an addresses table and our Job Entries map to a jobentries table, as in figure 2. Since our addresses and job entries are dependent value objects, they do not have their own identity outside of their parent Resume entity bean, and thus they do not have their own primary key, instead they are identified by a resumeID column in the addresses and job entries table.

Figure 2: EJB and dependent object DB mapping

Dependent Value Object should be made immutable, that is, they should have no set methods. In CMP, dependent objects cannot be passed to a client, they can only be accessed internally by an entity bean. One advantage to this restriction is that it ensures that any updating of data in an entity bean is done through the entity bean’s own business methods (encapsulation). In BMP, we are not faced with this restriction since dependent value objects are just regular java classes. In order to achieve the same benefit in BMP but still have the flexibility of passing our dependent value objects to clients, dependent value objects should be made immutable. This will ensure that the client doesn’t make changes to the value object assuming that his changes will be instantly reflected on the server, thus forcing the client to perform all changes through the entity beans remote interface.

Lazy Loading is a performance enhancement that allows dependent value objects to be loaded on demand. It avoids the wasteful practice of loading up all of an entity beans dependent value objects inside ejbCreate(), particularly if a client isn’t interested in the dependent data.

Lazy Loading is easy to implement. Each of your dependent value objects or collections can have get methods which:

Check to see if the internal dependent value object or collection is has been loaded (is null).

Calls the database and loads up the requested dependent data if not previously loaded

Passes the requested dependent value object (or collection) to the caller.

Once the dependent value object (or collection) has been read from the database, it can be cached inside the entity bean for future calls, as in our getAddress() and getJobs() in our Resume Bean (see downloadable example source at bottom of pattern).

In a BMP scenario, intelligent life cycle management is the programmers responsibility. Unfortunately, this is not trivial, particularly when dealing with a collection of dependent objects. A lot of life cycle management and database synchronization logic must be written to track dependent value objects as they are created, updated, and deleted. A good BMP implementation will only update the database with dependent objects that have been modified, created or deleted. It will also allow multiple operations (update, delete, etc) on dependent objects within one transaction and only synchronize the final state of an entity bean’s dependent objects with the database at transaction completion (in ejbStore).

Partitioning of persistence logic from business logic. Given the complexities of life cycle management of dependent value objects, many BMP developers choose to mix their persistence logic with their business logic by adding primary keys or dirty flags to dependent value objects, even interlacing their business logic with code necessary to track the life cycle of dependent value objects. To make programming with dependent value objects in BMP as easy as it in CMP, a developer should not add any special fields to his dependent value objects, nor should persistence logic be mixed in with business logic.

So how can a BMP developer achieve intelligent dependent value object lifecycle management and keep persistence logic separate from business logic? The answer is to abstract these details into a special collection class designed to track the lifecycle of dependent value objects that it is storing. Figure 3 illustrates a DependentValueSet, a special implementation of the Java 2 Set Collection. Along with supporting the normal operations of a Set (including add, remove, etc), the collection adds several new methods including an update(oldObject, newObject) method that takes two dependent value objects as a parameters, the original object and the newly updated one. Since dependent value objects (like CMP dependent objects) do not have any identity of their own (no primary key), we require that the original object be passed as a parameter so that our Set will know which object to replace.

Figure 3: The DependentValueSet Class

Using the DependentValueSet allows CMP developers to achieve separation of persistence logic from business logic because business methods need only interact with the normal operations of the Set interface and the extra update method. Dependent Value Objects are also kept clean; they do not need any special attributes added to track their state, as the DependentValueSet handles all of that transparently.

Our DependentValueSet implementation allows for intelligent lifecycle management by tracking which of our dependent objects were created, deleted or modified internally. This is extremely powerful as it allows the user to perform multiple operations on dependent value objects within one transaction, and synchronize the final state of our dependent value objects just once in ejbStore(). For example, the same dependent value object can be updated multiple times, but in ejbStore(), only one database update needs to be performed.

To support database synchronization, our DependentValueSet adds 5 extra methods:

addObjectFromDatabase(Object)

getObjectsToInsert()

getObjectsToDelete()

getObjectsToUpdate()

databaseHasBeenUpdated()

The addObjectFromDatabase method is meant to be called when dependent value objects are initially loaded from the database. It allows the DependentValueSet to track the objects that were initially in the database. The getObjectToXXX methods allow a BMP developer to query the DependentValueSet to find out which objects should be inserted, deleted, or updated, and write the dependent value object specific SQL code to handle these updates in ejbStore(). Once synchronization is complete, the DependentValueSet should be notified (databaseHasBeenUpdated ) so that it can clear itself up for the next transaction.

From our Resume example, we store our collection of job entries in a DependentValueSet. The entity beans remote interface exposes create, read, update, and remove (CRUD) operations for job entries, each of which delegate to methods on the DependentValueSet called jobentries, which handles all the life cycle tracking of the resumes jobs. At the end of the transaction (in ejbStore() ), we query our DependentValueSet to determine which job entries have been created, removed, or updated, and execute the appropriate SQL accordingly.

Each Resume only requires one Address dependent value object, thus we don’t need the advanced services of our DependetValueSet. Instead, we can manually get and set the object, and simply keep around an isAddresssModifed flag so that ejbStore() will know if our Address has been set in this transaction, and store it in the database if so.

Download the example source code including the full DependentValueSet.java implementation.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有