Using the primary key of the containing entity to hold Handles of related entity beans.
- By Grant Holland
- May 24, 2001
ARCHITECT'S CORNER
Entity bean relationships in EJB 1.1
Grant Holland
Listing 2. Using the primary key of the containing entity to hold Handles of related entity beans.
This example demonstrates how to store related key fields in the primary key object of the containing entity. The related key fields are stored as Handles. The example presents the pertinent parts of the code for the LineItem entity bean implementation.
The primary key class, LineItemPK, is presented in its entirety. Notice that we have declared the Handle of the Product EJBObject (productHandle field) as a field of the LineItemPk class in order to hold it during passivation.
Notice that there are two types of fields in the primary key class: identifying fields and relationship fields. Notice also that the toString(), equals() and hashCode() methods are overridden.
public class LineItemPK implements java.io.Serializable
{
public int lineItemID; // identifying field
public int orderID; // identifying field
public Handle productHandle; // relationship field
// Override toString() to use only the identifying fields.
public String toString()
{
return String.valueOf(orderID) + “+”
+ String.valueOf(lineItemID);
}
// Override equals() to use only the identifying fields.
public boolean equals( Object other )
{
if( other == null )
return false;
if( !(other instanceof LineItemPK ) )
return false;
if( (((LineItemPK)other).lineItemID == lineItemID) &&
(((LineItemPK)other).orderID == orderID) )
return true;
else
return false;
}
// Override hashCode()to use only the identifying fields.
public int hashCode()
{
return lineItemID;
}
}
For the LineItem entity bean implementation, the example will implement the code for a business method (getCost), ejbCreate, ejbFindByPrimaryKey and ejbActivate. ejbLoad, ejbStore, and other callbacks will not be shown in this example.
ejbCreate() first captures the identifying persistent data and the related EJB object from the parameter list. Then it writes the persistent fields to the database. (Notice that it also writes related key fields to the database. This if for use by ejbFind when instantiating a new instance of the entity.) Then ejbCreate calculates the Handle of the EJBObject, which it will use as its related key. After persisting what it needs to, it then creates a primary key object, inserts both the identifying field (lineItemID and orderID) and the relationship field (productHandle) into it, and returns the primary key object to the container. Notice that it obtains the Handle by invoking the getHandle method on the EJBObject.
package ejbrelationships.lineitem;
import javax.ejb.*;
import java.rmi.RemoteException;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.io.*;
import ejbrelationships.product.*;
public class LineItemEJB implements EntityBean
{
EntityContext ctx;
public int lineItemID; // persistent data
public int orderID; // persistent data
public int quantity; // persistent data
public String productName; // persistent data
public Product product; // related EJB object
public float getCost() throws RemoteException
{
// Invoke a biz method on the related Product entity bean
return quantity * product.getPrice();
}
public LineItemPK ejbCreate(
int lineItemID, // identity field
int orderID, // identity field
int quantity, // persistent field
Product product // related EJBObject
)
throws CreateException,RemoteException
{
LineItemPK pk;
try
{
// capture all field types
this.lineItemID = lineItemID; // persistent data
this.orderID = orderID; // persistent data
this.quantity = quantity; // persistent data
this.productName = // related key
((ProductPK)product.getPrimaryKey()).productName;
this.product = product; // related EJB obj
/*
// persist persistent data
< write “lineItemID” to persistent store >
< write “orederID” to persistent store >
< write “quantity” to persistent store >
// Serialize the Handle and write it to persistent store
// - ONLY NECESSARY FOR FINDERS on subsequent sessions
byte[] productSerHandle = serialize(product.getHandle( ));
< write productSerHandle to persistent store >
*/
// create and initialize Primary Key object
pk = new LineItemPK(); // make PK
pk.orderID = orderID; // capture identity field
pk.lineItemID = lineItemID; // capture identity field
// CAPTURE RELATIONSHIP HANDLE IN PRIMARY KEY OBJECT!
pk.productHandle = (Handle)product.getHandle();
}
catch(Exception e)
{
throw new CreateException(e.getMessage());
}
return pk;
}
// Before passing it as the parameter to this method, the client
// will initialize the primary key object with identifying fields.
// Client may set the related entity Handle to null,
// if it is unknown to him.
// If so, this method will read the serialized Handle
// from persistent store, as placed there by ejbCreate,
// and put it into the primary key object.
// The primary key object will be returned.
public LineItemPK findByPrimaryKey( LineItemPK pk )
{
// PK as received may only be initialized with
// orderID and lineItemID – and not with productHandle.
// productHandle can be set to <null> by client
// if unknown to him.
// If so, we must read and deserialize productHandle from
// persistent store and set it into the PK
// before returning it.
if(pk.productHandle == null )
{
// If so, orderID and lineItemID must be used
// to locate state for this entity on persistent store.
< Read any persistent data from persistent store into
into resultSet, including the serialized Product Handle,
which was persisted there by ejbCreate. >
// get serialized Product Handle from the result set.
byte[]productSerHandle
= resultSet.getByteArray(“productserhandle”);
// deserialize Handle and put it into the primary key
pk.productHandle = deserialize(productSerHandle);
}
return pk;
}
public void ejbActivate() throws RemoteException
{
// Obtain primary key from entity context
LineItemPK pk = (LineItemPK) ctx.getPrimaryKey();
try
{
// THIS IS THE POINT OF THE REFINED TECHNIQUE
// reconstitute related EJB object from primary key
Handle productHndl =
((LineItemPK)ctx.getPrimaryKey()).productHandle;
product = (Product)productHndl.getEJBObject();
}
catch(Exception e)
{
throw new RemoteException(e.getMessage());
}
}
}