| CONTENTS | PREV | NEXT | INDEX | Designing Enterprise Applications with the J2EETM Platform, Second Edition |
An entity bean represents an object view of business data stored in persistent storage or an existing application. The bean provides an object wrapper around the data to simplify the task of accessing and manipulating it. This object view of data lends itself to software reuse. For example, an entity bean representing customer account information can be used by order management, user personalization, and marketing in a uniform way.
An entity bean allows shared access from multiple clients and lives beyond the duration of the client's session with the server. If the state of an entity bean is being updated by a transaction at the time of a server crash, the entity bean's state is automatically reset to the state of the last committed transaction.
A bean provider can use the following entity bean characteristics as guidelines when deciding whether to model a business object as an entity bean:
- Representing persistent data
If the state of a business object needs to be stored in a persistent storage and its behavior primarily represents or is dependent upon the manipulation of such state, then it should be modeled as an entity bean.
- Representing objects with clearly-defined identity
Instances of business objects typically have their own unique identity. A business object's identity distinguishes one object instance from another and makes it possible to locate a particular business object. For example, a business object representing a purchase order has a purchase order number that uniquely identifies that order. Entity beans provide a persistent identity for business objects. They should be used when accessing an object by its identity is important to the application.
- Providing concurrent access by multiple clients
When multiple clients need to share the state and behavior of a business object, that object should be modeled as an entity bean. An entity bean maintains persistent state. However, this state is not specific to a particular client, but instead it is representative of the persistent state of a business object. By modeling business objects as entity beans, a bean provider can rely on an EJB server or container to ensure appropriate synchronization for entity beans when they are accessed concurrently from multiple transactions.
- Providing robust, long-lived persistent data management
When a business object exists independently of user sessions and its state must survive container restarts, model it as an entity bean. Entity bean state survives container restarts and crashes and does not depend on a particular user session.
- Persisting data in a portable manner
Use an entity bean to model persistent data that needs to be accessed in a portable way. Using entity beans with container-managed persistence guarantees that the bean's view of its own persistent state is always the same, regardless of how it is stored in the data storage system used in its deployment environment.
- Providing access through queries
Unlike session beans and message-driven beans, entity beans with container-managed persistence provide a query capability and can be located by the container based on their identity or state. The bean provider can define queries that allow entities to be automatically found by the container on the basis of the values of their persistent data--such as customer location, order quantity, order identification number, and so on.
- Simplifying transaction handling
Use an entity bean to have the container handle the transaction logic for the persistent data. By doing so, the developer does not have to include transaction handling code with the entity bean's business logic.
The protocol for transferring the state of an entity between the enterprise bean instance and the underlying persistent store is referred to as object persistence. An entity bean can implement persistence in the following ways:
With bean-managed persistence, the bean provider writes database access calls. These calls can be coded directly into the enterprise bean class or encapsulated in a data access object that is part of the entity bean. If data access calls are coded directly in the enterprise bean class, it may be more difficult to adapt the entity component to work with a database that has a different schema or with a different type of database. Encapsulating these calls in a data access object makes it easier to adapt the enterprise bean's data access to different schemas or different database types, but requires regeneration of the data access objects used by the bean. The data access object approach should therefore only be used when use of container-managed persistence is not appropriate for the individual bean type. Data access objects are discussed in Section 5.7.5 on page 160.
With container-managed persistence, the bean provider relies on the container to manage the access to the persistent state of the bean. Unlike the case of bean- managed persistence, the bean provider does not have to write any database access calls.
The EJB 2.0 architecture significantly improves upon container-managed persistence. Rather than defining instance variables in the entity bean class for the bean state that is to be stored to the database, as with earlier EJB specifications, the bean provider defines public abstract accessor methods (get and set methods) for each container-managed persistent and container-managed relationship "field." The container provides the implementation of the get and set methods used at runtime. The "field" itself is invisible to the bean.
Container-managed persistence simplifies the task of writing entity beans, because the container takes the responsibility of generating the code to access the data source. Bean developers should take advantage of this feature and use container-managed persistence whenever possible to delegate to the container the task of maintaining the persistence state of an entity bean.
5.4.2.1 Example: A Customer Account BeanThe concept of a customer account is central to all clients in many e-commerce applications. Multiple clients need to share behavior such as creating an account, verifying an existing account, and updating account information. Updates to the state of an account object need to be written to persistent storage. The account object needs to live even when the client's session with the server is over. Therefore, in the sample application, an account object is modeled as an entity bean.
An Account bean conforming to the EJB 2.0 specification that uses container-managed persistence does not declare instance variables for its container-managed persistent fields. Instead, it uses accessor methods for the data fields, as shown in Code Example 5.1.
public abstract class AccountEJB implements EntityBean {
// Container-managed persistent fields
public abstract String getStatus();
public abstract void setStatus(String status);
...
}
| Code Example 5.1 Account Bean Implementation |
5.4.2.2 Container-Managed Relationships
The EJB container provides automatic management of both the persistent state of entity beans and the persistent relationships among entity beans. Container-managed relationships may be unidirectional or bidirectional, and they may be of any cardinality. That is, a relationship may be a one-to-one relationship, a one-to-many relationship, or a many-to-many bidirectional relationship. Keep in mind that relationship integrity is maintained based on the direction of the relationship.
Relationships are implemented as container-managed relationships fields. Like persistent fields, container-managed relationships fields are abstract bean fields that are defined and accessed by public abstract get and set accessor methods in the enterprise bean class. The type of a container-managed relationship field is either an entity bean local component interface type or a collection of an entity bean local component interface type.
Entity bean relationships are manipulated by simply using the get and set accessor methods and the methods of the java.util.Collection API. Any change made to a container-managed relationship field is reflected in the relationship between the entity beans involved in the relationship and is automatically persisted by the container. The container also automatically enforces the integrity constraints of each relationship. For example, if the entity bean Supplier has a many-to-many bidirectional relationship with the entity bean Item, then if a supplier S stops supplying an item I, the container will automatically remove supplier S from the set of suppliers available to supply item I.
An entity bean must provide a local client view so that it can be used as the target of a container-managed relationship. It is important to note, however, that an entity bean is not required to have a local client view to make use of container-managed persistence.
The entity bean's deployment descriptor contains a description of the bean's abstract persistence schema. This schema is an abstract representation of an entity bean's persistent state and relationships, independent of the bean's implementation in a particular container or particular data store.
5.4.2.3 EJB QL, the EJB Query LanguageA further advantage of using entity beans with container-managed persistence is that they support the use of EJB QL, the Enterprise JavaBeans Query Language. EJB QL is a query language similar to SQL that is new to EJB 2.0. By allowing the bean provider to specify queries defined on an entity bean's abstract persistence schema, EJB QL provides a datastore-independent, portable way to express how to find an entity object or collection of entity objects. EJB QL queries can also find container-managed persistent field values.
The container maps a query in EJB QL to operations on the underlying persistent data store. For example, in the case of a relational data store, the container maps an EJB QL query to an SQL query.
For each EJB QL finder or select method (except findByPrimaryKey), there must be a corresponding EJB QL query that defines its behavior. The container implements the finder or select method by translating the EJB QL statement into a query on the persistent store, such as a query on a relational database.
An EJB QL query always has a SELECT clause and a FROM clause, and may also have a WHERE clause that limits the query result set. The result of an EJB QL query may be either an entity bean or a persistent value, or collections of these.
For example, the Code Example 5.2 demonstrates how the sample application uses an EJB QL query for a finder method findOrdersByStatus to find orders that are in a particular status, such as PENDING.
SELECT DISTINCT OBJECT(o) FROM SupplierOrder o WHERE o.poStatus = ?1
| Code Example 5.2 EJB QL Query Example |
The query returns SupplierOrder objects, as indicated by the expression OBJECT(o). The identifier o is analogous to an SQL correlation variable. The WHERE clause limits the orders to those whose status matches the value of the first parameter passed to the query (denoted by the expression ?1).
Here are some guidelines for writing queries in EJB QL:
5.4.2.4 Benefits of EJB 2.0 Container-Managed Persistence
- Utilize parameters and write general queries that serve multiple purposes. For example, Code Example 5.2 uses the expression
?1rather thanPENDINGto implement a general query that can be used to find orders in any status, not justPENDING.- Use
distinctto eliminate duplicates in a returned collection of objects. For example, Code Example 5.2 usesdistinctto eliminate duplicate orders from the result of the query.- Write select methods for complex queries that you do not want exposed to clients. For example, to avoid exposing an employee's salary to clients, an employee bean may use a select method to programmatically calculate an employee's bonus based on salary.
- Write complex select queries to select results on a tightly-coupled network of entity beans that can return data about the network, entity object, or container-managed persistent field data.
The EJB 2.0 approach to container-managed persistence offers a number of benefits:
- Provides a layer of data independence
Container-managed persistence provides for data independence in two locations: between the client view and the entity bean and between the entity bean and the persistent store.
- Promotes an entity bean's portability
With the EJB 2.0 container-managed persistence approach, it is easier to migrate an entity bean to different EJB containers and to different types of persistent stores. This migration can be done without recompiling the bean.
- Provides a datastore-independent query language
EJB QL provides a way to specify queries for the finder and select methods of entity beans with container-managed persistence that is independent of their implementation in a particular database or other persistent store. It therefore allows such entity beans to be portable across particular storage systems.
- Provides for faster development
Because the bean provider does not have to be concerned with the details of persistence management, development of the entity bean can be faster and simpler and the developer is further freed from systems-level concerns.
Despite the many advantages of container-managed persistence, there are situations in which it is more appropriate to develop entity beans using the bean-managed persistence approach. These include the following:
- Use bean-managed persistence when you need exact control over the database schema or need to customize code to match a specific legacy database schema.
- Use bean-managed persistence when it is important that the application be very finely tuned against the database that is in use.
- Use bean-managed persistence when portability is not an issue. Even in this case, however, it is recommended that data access objects (DAOs) be used. DAOs better enable the bean to be adapted to a different database schema or to evolve into an entity bean with container-managed persistence at a later date. See Section 5.7.5 on page 160.
- Use bean-managed persistence when the query needs of the application exceed the current capabilities of EJB QL. While EJB QL will continue to develop, it is not yet able to express a number of queries that are expressible in SQL.
- Use bean-managed persistence when your persistent store is not a database system or is a legacy database system that is not likely to be supported for container-managed persistence.