- What's New in EJB 2.0
- The EJB Query Language (EJBQL)
- Container-Managed Persistence
- Message-Driven Beans
Container-Managed Persistence
Container-managed persistence has undergone a major overhaul between version 1.1 and 2.0 of the EJB specification. The interesting thing about these changes is that they are transparent to any clients of your entity beans. That is, the implementation changes substantially, but the Home and Remote interfaces stay the same. A client can't tell whether you're using the new EJB 2.0 CMP or the old EJB 1.1 CMP.
One of the first things you notice about an EJB 2.0 CMP bean is that the class must be declared as abstract. Second, you don't declare variables to hold persistent fields under EJB 2.0. That is, if your bean has a persistent string field called name, you don't declare a String variable in the class. Instead, you create get and set methods for the field. When you deploy the bean, the container generates a concrete implementation of the class that includes the persistent fields.
Here is an example of a simple EJB 2.0 CMP entity bean implementation:
import java.rmi.*; import java.util.*; import javax.ejb.*; import java.sql.*; import javax.sql.*; import javax.naming.*; public abstract class SimpleBeanImpl implements EntityBean { /** The entity context provided by the EJB container. An entity bean must hold on to the context it is given. */ private EntityContext context; /** An EJB must have a public, parameterless constructor */ public SimpleBeanImpl() { } /** Called by the EJB container to set this entity's context */ public void setEntityContext(EntityContext aContext) { context = aContext; } /** Called by the EJB container to clear this entity's context */ public void unsetEntityContext() { context = null; } /** Called by the EJB container when a client calls the create() method in the home interface */ public String ejbCreate() throws CreateException { return null; } /** Called by the EJB container after ejbCreate to allow the bean to do any additional setup that may be required. */ public void ejbPostCreate() throws CreateException { } /** Called by the EJB container to tell put the bean into active mode */ public void ejbActivate() throws EJBException { } /** Called by the EJB container to tell this bean that it is being deactivated and placed back into the pool */ public void ejbPassivate() throws EJBException { } /** Called by the container to tell the entity bean to read its data from the database */ public void ejbLoad() throws EJBException { } /** Called by the EJB container to tell the entity bean to write its data out to the database */ public void ejbStore() throws EJBException { } /** Called by the EJB container to tell this bean that it has been removed. */ public void ejbRemove() throws EJBException { } // Implement the get/set methods for all the data elements public abstract String getName(); public abstract void setName(String aName); public abstract int getAge(); public abstract void setAge(int anAge); }
EJB 1.1 fails to deal with the fact that you often need to declare relationships between object. An order has multiple line items, and an aircraft may be assigned to one or more flights. In your Remote interface, you declare get and set methods for traversing a relationship. If an object can be related to a single object (for example, a line item can belong to only one order), you create get/set methods to enable you to get and set the related object. For example, to specify the Order for a LineItem, the Remote interface for LineItem must contain methods like this:
public Order getOrder() throws RemoteException; public void setOrder(Order anOrder) throws RemoteException;
When an item may be related to multiple objects (for example, an order can have multiple line items), your get/set methods must deal with collections. For example, the following declaration lets you get and set the collection of LineItem objects that belong to an Order:
public Collection getLineItems() throws RemoteException; public void setLineItems(Collection lineItems) throws RemoteException;
Sometimes you need to split an entity bean across multiple database tables, but you don't want to create entity beans for every table. For example, you might not want to make a LineItem entity bean, but instead you want to manage line items from inside the Order object. EJB 2.0 lets you create special dependent objects that are not visible outside the entity bean[md]that is, they can't be used by a client. Although a dependent object isn't a full-blown entity bean (it has no Home or Remote interfaces), the container will still manage a dependent object's persistence.
Because a dependent object has no Home interface, you need a way to create new dependent object. You can't use a constructor because you define the dependent object with an abstract class, just like you do with the entity bean. The solution for this is that you define special create methods in your entity bean implementation class. For example, in the Order class, you might define a createLineItem method to create new LineItem objects.