|
|
| ||||||||||||||||||
|
Entity beans provide a clear model to represent persistent business objects in applications and their design. In object models, simple JavaTM objects are normally represented in a straightforward way, but do not include the transactional persistence management functionality usually required for business objects. Entity beans not only allow the same type of modelling and thinking about business objects in an object model, but they also encapsulate persistence mechanisms while hiding all complexity behind the bean and container services. This allows applications to manipulate them as Java object references. By hiding the persistent form and persistence mechanism from any calling code, entity beans allow for creative persistence optimizations by the container, while keeping the data store open and flexible, only to be determined at deployment time. Based on Enterprise JavaBeansTM (EJBTM) development projects, which make extensive use of object-oriented methodologies and result in heavy use of entity beans, Sun engineers have learned about using entity beans in the real world. This article elaborates on such development experience to:
Use Container-Managed Persistence When You Can Container-managed persistence (CMP) not only eases
the job by requiring a lot less coding, but also enables many optimization
possibilities within the container and the container-generated database
access code. The container has access to the in-memory buffer of the bean
which allow it to monitor for any change in the buffer. Storing the buffer
to the database before committing a transaction can be avoided if the
buffer has not changed. This avoids unnecessary expensive database calls.
Another instance of this optimization is calling
CMP allows for optimizing these two database accesses into a single database access whenever it makes sense to do so, allowing retrieval of both the key and the record data in one database call. Write Code that Supports Both Bean- and Container-Managed Persistence In many cases the EJB's author does not have control over how the
EJBs are deployed and whether the container used for deployment will
support CMP. Also, the deployer may choose to use bean-managed persistence
(BMP) in the target container. You must find a way to implement the beans
to allow BMP deployment without disrupting the support for the potentially
more optimized CMP mechanism. One easy way to achieve this is to separate
pure business logic from the persistence mechanism. Implement the business
logic in your CMP class, which can be deployed alone if CMP is chosen.
Then implement the persistence code into the BMP class, which inherits
from the CMP class. This preserves all the business logic of the CMP
superclass and adds database access code in the BMP subclass, as shown in
figure 1.
![]() Figure 1: Separation between CMP and BMP
To solve these problems, you can change the current model for the BMP class to delegate all the persistence code to a helper class and leave a skeleton in the BMP class. This kind of helper class is called a Data Access Object (DAO). You can provide multiple DAO classes by subclassing a DAO interface, which then allows the correct DAO subclasses to be instantiated. This is shown in Figure 3. There are many ways to choose and instantiate the correct DAO subclass, for example, by reading environment entries or by figuring out the DB type and choosing the most appropriate subclass.
![]() Figure 3: Delegation and allowing for alternate DAO implementations.(Click to enlarge) Using this model, both the CMP implementation and the DAOs that contain the implementations can be easily extended; everything but the BMP classes can be extended. Because these BMP classes contain a skeleton of delegation code that looks almost the same for every entity bean, and the instantiation code to choose the right DAO object, you can easily copy from one bean to another with very little modification. Also, you could eventually automatically generated them with a tool. While it is possible to extend an entity bean to reuse the logic provided by another entity bean, it is not possible in the EJB 1.1 specification to allow extension of entity types that extend the home interface. Finders and create calls are theoretically always remote calls. The generated stubs will never represent a subtype, although logically you might want to (for instance, to use them as a factory method). This prevents the use of many useful design patterns in EJB implementations that follow the EJB 1.1 specification.
Minimize Database Access in ejbStores
When using CMP, the bean has absolutely no control over
Whenever the bean is deployed using BMP, it is very useful to maintain
a There are caveats with this technique. Since the Philosophically, the writer of an EJB should not have to deal with
system-level issues like buffer handling. Unfortunately EJB 1.1 using BMP
does not provide any alternative for such an optimization, so the bean
author still has to set this Always Cache References Obtained from lookups and find Calls
Reference caching is useful for both entity beans and session beans. JNDI lookups of EJB resources, such as DataSources, bean references, or even environment entries can be fairly costly, and it is simple to avoid redundant lookups. To solve this problem, always:
The Calls to the finders of other entity beans are also heavyweight calls.
While these calls may or may not fit into bean initialization callbacks
like Always Prepare Your SQL Statements
This optimization is useful for all code using SQL to access relational databases. And since most of the current EJB implementations use relational databases, this rule is also very useful for EJB development where the author of the bean has to write database access code. For each SQL statement processed by the database, the database has to spend time compiling the statement before executing it. Good relational databases, however, can cache the statement and its compiled form and match new statements against the cache to retrieve its compiled form. However, in order to use this optimization, the new statements must exactly match the old statements.
When you use the statement, data is then passed to it and the statement gets executed. Normally, the statement is compiled at prepare time, but subsequent prepares already match the cache and are not recompiled. This technique promotes very high statement cache hit ratios (close to 100%) that minimizes the amount of statement compilations. For small database accesses, this can decrease the statement execution time by up to 90%. Close all Statements Properly
When dealing with database access code in BMP implementations, never
leave the statements open after database access calls. Each open statement
corresponds to an open cursor in the database. (While the garbage
collector eventually claims the open statement and closes it at garbage
collection (GC) time, you do not have control over the time the GC kicks
in. Do not enforcing GC by calling the Also, be sure to catch all exceptions properly when closing the statements. An exception in closing one statement must not cause other statements to be ignored and left open. Avoid Deadlocks
Application code does not have direct control when
If multiple entity beans or multiple entities are involved in a
transaction, the sequence in which Looking on the bright side, ideally, container-controlled access and locking in EJBs should allow the container to account for deadlocks and free the developers/deployers from such worries. Unfortunately, few if any of the currently available commercial application servers do a good job in ordering database locks, leaving deadlock problems in complex entity bean deployments to the deployer. The applicable rule, at least at the time of this writing, is to assume
the container will invoke the database access calls of the beans in the
same sequence a transactional method of the bean is first accessed as part
of the transaction. To make this clearer, consider the following example:
Assume entity bean As application servers become more intelligent and know how to order database accesses, authors and deployers can be less careful on the bean access sequence. However, code that strictly deals with invocation order as in the example provided will continue to run on future servers as well as today's. The Going ForwardThese rules, when utilized with entity-intensive developments and deployments, can significantly help increase the performance and flexibility of the beans, allowing them to adapt to different persistent storage types while minimizing their load on the container and the underlying system. This gives the deployer the flexibility to choose the most suitable deployment infrastructure and all allowing the beans to make efficient use of the infrastructure provided. In other words -- write once run anywhere, efficiently.
For More Information
About the Author
Akara Sucharitakul was one of the developers of the ECperf benchmark and other J2EE server based applications inside Sun. He has more than 5 years of experience with Java technology and has been working on J2EE technology since its early days. Reader FeedbackTell us what you think of this tutorial.
Have a question about programming? Use Java Online Support. |