Entity beans are the most controversial aspect of the Enterprise JavaBeans (EJB) and J2EE. Specifications: They are responsible for managing persistence of business objects to a datasource, usually a relational database.
Due to performance and scalability problems, entity beans have given EJBs a bad name. But unfortunately, unless you want to hand-code SQL and JDBC calls, entity beans are the only means defined in the EJB 2.1 and J2EE 1.4 specifications for persisting objects.
That is not to say there are no other options outside the specifications for persisting Java objects. In fact, Java has another persistence specification called Java Data Objects (JDO); see http://java.sun.com/products/jdo/ for more information.
There are also a number of open source and commercial object-to-relational mapping frameworks available, including the popular open source Hibernate framework www.hibernate.org from the JBoss group.
The Java persistence space is rapidly changing. As of this writing, the finishing touches are being placed on the EJB 3.0 Specification (JSR 220), which will change Java persistence once again.
One of the EJB 3.0 Specification goals is to merge EJB and JDO into a common persistence model that works within a J2EE application server as well as for a simple J2SE application.
Entity Beans Overview
As mentioned in the introduction, entity beans are the primary abstract method of persistence in the EJB 2.0 Specification. Rather than managing connections, writing select and update statements, or interacting directly with a database through JDBC, you interact with an object using its getters and setters.
This object represents a business entity such as an employee, ticket, or customer. Typically, each entity bean instance represents a row in the database. Each entity bean must define a primary key to uniquely identify an instance of the entity.
The primary key can be a specialized class or a standard Java class such as java.lang.String or java.lang.Integer.
Specialized primary key classes may represent a single or compound field in the database and by convention have a class name that ends in PK. For example, the TicketBean in Figure 9-1 could have a TicketPK class as its primary key rather than java.lang.Integer.
Specialized primary keys must override the equals and hashcode methods so they can be used to look up entity beans from internal caches. They must also be serializable and contain a zero argument constructor so they can be sent across the network.
In addition, it is a good idea to override the toString method to print out something descriptive. This can make debugging easier because the application server will call it when throwing exceptions.
There are two types of entity bean persistence mechanisms: container-managed persistence (CMP) and bean-managed persistence (BMP).
For CMP, the EJB container or application server is responsible for managing the persistence and all the entity bean life cycle methods. When the bean is deployed, the application server generates the SQL code for the mapping between the table and bean attributes. The mapping is defined in the deployment descriptors, both standard and container specific.
The developer does not have to allow the container to manage persistence. If a developer prefers, he or she can code the SQL in the bean life cycle methods. This is referred to as BMP and is commonly practiced when the datasource has a schema that does not map well to the entity.
For example, an entity may have its attributes defined in multiple tables. This often happens in nonrelational legacy datasources. To implement BMP, you must write and execute SQL in the entity life cycle methods of ejbCreate, ejbRemove, ejbFind, ejbLoad, and ejbStore.
CMP is generally preferred over BMP by the EJB 2.1 Specification and application server vendors. This is because CMP provides more independence from the datasource. With CMP, it is not possible for database vendor-specific SQL to accidentally be introduced. This makes migrating an application to a new database easier.
In addition, CMP commonly has better performance because the application server vendor can take advantage of special optimizations. Like session beans, entity beans can expose their getters and setters to both remote and local clients. However, unlike with session beans, exposing entity bean getters and setters remotely is never a good idea.
This is referred to as fine-grain access and is the primary reason entity beans suffer from performance problems. The performance problems stem from each call to a getter or setter being a separate remote method call, which incurs all the network overhead. For stable VPS servers please view VPS java hosting offer on our website.
For example, if a client wanted to display the ID, summary, details, and submitted date of a trouble ticket, it would require five remote calls. One remote call would be made to find the entity and four others to call the getter methods. Instead, only course-grain access should be used for remote EJBs using the Session Façade and Data Transfer Object patterns.
Fortunately, XDoclet helps implement this pattern by generating a data object that represents our entity bean. It even provides a convenience method on the entity bean to get the data object.
Like a local session bean, a local entity bean requires a local interface, a local home interface, a bean class, and some deployment descriptors. The local interface must extend the javax.ejb.EJBLocalObject. The local interface contains getters and setters for each of the entity bean attributes.
A local entity bean also requires a local home interface. The local home interface must extend javax.ejb.EJBLocalHome. The local home interface contains methods for controlling the life cycle of an entity bean. For example, it typically contains one or more create methods, finder methods, and a remove method. The create methods are called when a new entity is required.
Under the covers it performs an insert in the datasource with the data it is provided. All columns in the table that have a NOT NULL constraint should be passed into the create method and set on the entity bean or defaulted in the create method.
Otherwise, when the record is inserted, an exception will be thrown stating the table constraints have been violated. The finder methods are used to locate and load the entities into memory. They may return a single local interface or a collection of local interfaces.
At a minimum, there is a findByPrimaryKey method required, which the application server implements on your behalf. Other finder methods may require a specialized SQL syntax called EJB Query Language, or EJB QL, to be set in the deployment descriptors.
Lastly, the remove method permanently removes the entity by deleting the row in the datasource. The home interface must be looked up via JNDI. The JNDI lookup returns an application server–specific proxy implementation that implements the home interface.
In addition to the standard ejb-jar.xml deployment descriptor and a container specific EJB deployment descriptor, CMP entity beans also require a container specific CMP deployment descriptor.
The CMP deployment descriptor defines the bean-to-table mappings as well as the field-to-column mappings. Depending on the application server, it may also contain optimization hints, generated key hints, and instructions to create the tables if they do not exist.