Oracle8i Enterprise JavaBeans Developer's Guide and Reference Release 3 (8.1.7) Part Number A83725-01 |
|
There are two methods for managing the persistent data within an entity bean: bean-managed and container-managed persistence. The main difference between bean-managed and container-managed persistent beans is defined by who manages the persistence of the entity bean's data.
In practical terms, the following table provides a definition for both types and a summary of the programmatic and declarative differences between them:
Bean-Managed Persistence | Container-Managed Persistence | |
---|---|---|
Persistence management |
You are required to implement the persistence management within the
For example, the |
The management of the persistent data is done for you. That is, the container invokes a persistence manager on behalf of your bean.
You use |
Finder methods allowed |
The |
Only the |
Defining CMP fields |
N/A |
Required within the EJB deployment descriptor. The primary key must also be declared as a CMP field. |
Mapping CMP fields to resource destination. |
N/A |
Required. Dependent on persistence manager. |
Definition of persistence manager. |
N/A |
Required within the Oracle-specific deployment descriptor. See the next section for a description of a persistence manager. |
You can choose to have the container manage your persistent data for the bean. You have less to develop and manage, as the container stores and reloads your persistent data to and from the database.
When you use container-managed persistence, the container invokes a persistence manager class that provides the persistence management business logic. For this release, the only supported persistence manager is Oracle Persistence Service Interface Reference Implementation (PSI-RI).
To enable the container to manage your persistent data, you need to perform the following:
If you do not want to manage your persistent data, choose to have your bean managed by the container. This means that you do not have to implement some of the callback methods as the container and the persistence manager performs the persistence and primary key management for you. The container will still call these methods--so you can add logic for other purposes. You still must provide at least an empty implementation for all callback methods.
The following table details the implementation requirements for the bean class' callback functions:
Oracle enables you to perform a SQL query against the persistent data table through a CMP-only finder method with a find<
name>
naming syntax. This method takes a String that denotes the "where
" clause of a SQL query. Thus, the String would include the entire statement except for the "select
* from
<table"
. If you supply an empty string, all values are selected from this table.
You must define any such finder method within the Home interface. The container will provide the implementation for satisfying the where clause for the finder method.
For example, the following defines finder methods within the home interface, where one retrieves all customers and the other retrieves a single customer. Notice how the findAllCustomers
method, which retrieves all customers in the table, returns an Enumeration
.
public CustomerfindByWhere
(String whereString)
throws RemoteException, FinderException;
public java.util.EnumerationfindMultipleCustomers
(String whereString)
throws RemoteException, FinderException;
If you want to retrieve a single customer, provide the name, the SQL would be constructed as follows:
select * from customer where name = "Smith, John";
The findbyWhere
finder method would include the entire statement except for the "select * from customer
". It assumes that you want to select against the persistence table, as follows:
Customer find_customer = findByWhere ("where name = ", + custname);
If you want to select a few rows from employee based upon a certain condition, the SQL would be constructed as follows:
select * from customer where item_bought = treadmill order by name;
The find<
name>
method, which in this example is findByWhere, would include the entire statement except for the "select
* from
employee
". It assumes that you want to select all matches against the persistence table. This is demonstrated below:
Enumeration customer_list = findMultipleCustomers(
"where item_bought = treadmill order by name");
Or, if you wanted a full customer listing, provide an empty string. The container will invoke a "select
* from
customer
" and retrieve all records.
Enumeration customer_list = findMultipleCustomers();
The main difference between defining a bean-managed and container-managed persistent primary key is that the fields within the key must be declared as container-managed persistent fields in the deployment descriptor. All fields within the primary key are restricted to be either primitive, serializable, and types that can be mapped to SQL types. See "Persistence Fields" for more information.
You can define your primary key in one of two ways:
Define your primary key as a container-managed persistent field and its type within the deployment descriptor. The following shows the primary key, custid
, declared as a <cmp-field>
and <primkey-field>
and its type declared within the <prim-key-class>
:
<enterprise-beans> <entity> <description>customer bean</description> <ejb-name>/test/customer</ejb-name> <home>customer.CustomerHome</home> <remote>customer.Customer</remote> <ejb-class>customerServer.CustomerBean</ejb-class><persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<primkey-field>custid</primkey-field>
<reentrant>False</reentrant><cmp-field><field-name>custid</field-name></cmp-field>
<cmp-field><field-name>name</field-name></cmp-field>
<cmp-field><field-name>addr</field-name></cmp-field>
</entity> </enterprise-beans>
The primary key variable declared within the bean class must be declared as public
.
This should be a Java type that can be mapped to a SQL type through SQLJ. Also, this object must be serializable. See "Entity Bean Elements" for a full description.
If your primary key is more complex than a simple data type, you define the fields that make up the primary key as container-managed fields within the deployment descriptor. Then, you declare these fields as the primary key within a class. This class must be serializable. Also, all primary key variables declared within the bean class must be types that can be mapped to SQL types.
Within the bean class, the primary key variables must be declared as public
. Also, you must provide a constructor with no arguments for creating an empty primary key instance.
Within the serializable primary key class, you implement the equals
and hashCode
methods to provide for an implementation specific to this primary key.
The following example is a cruise ship cabin bean primary key that identifies each cabin with ship name, deck name, and cabin number.
package cruise; public class CabinPK implements java.io.Serializable { //Ship names { Castaway, LightFantastic, FantasyRide } public String ship; //Deck names { Upper Promendade, Promenade, Lower Promenade, Main Deck, Lower Deck } public String deck; //Cabin numbers A100-N300 public String cabin; //empty constructor public CabinPK ( ) { } public boolean equals(Object obj) { if ((obj instanceof CabinPK) && (((CabinPK)obj).ship == this.ship) && (((CabinPK)obj).deck == this.deck) && (((CabinPK)obj).cabin == this.cabin)) return true; return false; } public int hashCode() { return ((ship + deck + cabin).hash); }
The class that defines the primary key is declared within the XML deployment descriptor, as follows:
<enterprise-beans> <entity> <ejb-name>CabinBean</ejb-name> <home>cruise.CabinHome</home> <remote>cruise.Cabin</remote> <ejb-class>cruiseServer.CabinBean</ejb-class> <persistence-type>Container</persistence-type><prim-key-class>cruise.CabinPK</prim-key-class>
<reentrant>False</reentrant><cmp-field><field-name>deck</field-name></cmp-field>
<cmp-field><field-name>cabin</field-name></cmp-field>
... </enterprise-beans>
See "Entity Bean Elements" for a full description of the deployment descriptor definition.
You must initialize all CMP fields, including the primary key, within the ejbCreate
method. The ejbCreate
method for the purchase order example initializes the primary key, ponumber
, to the next available number in the purchase order number sequence.
// The create methods takes care of generating a new PO and returns
// its primary key
public String ejbCreate
() throws CreateException, RemoteException
{
String ponumber = null;
try {
//retrieve the next available purchase order number
#sql { select ponumber.nextval into :ponumber from dual };
//assign this number as this instance's identification number
#sql { insert into pos (ponumber, status) values (:ponumber, 'OPEN') };
} catch (SQLException e) {
throw new PurchaseException (this, "create", e);
}
return ponumber;
}
All container-managed persistent fields must be declared as public
within your bean class. They cannot be transient. In addition, these fields are restricted to be either primitive, serializable, and types that can be mapped to SQL types. See Table A-2, "Unsupported Java Types for Persistent Variables" for more information.
The container invokes a persistence provider for managing your CMP bean. This release supports Oracle Persistence Service Interface Reference Implementation (PSI-RI). For more information on defining the provider, see "Defining Container-Managed Persistence" for a full description.
The following shows the portion of the Oracle-specific deployment descriptor that defines the persistence manager:
... <persistence-provider> <description> specifies a type of persistence manager </description> <persistence-name>psi-ri</persistence-name> <persistence-deployer>oracle.aurora.ejb.persistence.ocmp.OcmpEntityDeployer</p ersistence-deployer> </persistence-provider> <persistence-descriptor> <description> This specifies a particular type of persistence manager to be us ed for a bean. param is where you would put bean specific persistence info in t he format of params. The deployment process just passes what's in the param to the persistence deployer. For the baby persistence, we do parse the persistence -mapping but for other persistence backend we don't do anything with the params </description> <ejb-name>customerbean</ejb-name> <persistence-name>psi-ri</persistence-name> <psi-ri> <schema>SCOTT</schema> <table>customers</table> <attr-mapping> <field-name>custid</field-name> <column-name>cust_id</column-name> </attr-mapping> <attr-mapping> <field-name>name</field-name> <column-name>cust_name</column-name> </attr-mapping> <attr-mapping> <field-name>addr</field-name> <column-name>cust_addr</column-name> </attr-mapping> </psi-ri> </persistence-descriptor> </oracle-descriptor>
All CMP data fields defined within your bean must be declared within the deployment descriptor in the <cmp-field>
element. See "Entity Bean Elements" for a full description. In addition, you must map these fields to the intended database table and respective columns. See "Persistence Fields" for more information.
The following is a portion of the Oracle-specific deployment descriptor, which maps the primary key and any container-managed persistence fields from the customer example (with the single primary key field) to the database table and column that the persistence provider stores the values for these fields within. Specifically, the container-manager stores the persistent fields into the customers table in SCOTT's schema. The persistent fields are mapped as follows:
Persistent Field | Table Column |
---|---|
custid (primary key) |
cust_id column in the customers table |
name |
cust_name column in the customers table |
addr |
cust_addr column in the customers table |
<psi-ri> <schema>SCOTT</schema> <table>customers</table> <attr-mapping> <field-name>custid</field-name> <column-name>cust_id</column-name> </attr-mapping> <attr-mapping> <field-name>name</field-name> <column-name>cust_name</column-name> </attr-mapping> <attr-mapping> <field-name>addr</field-name> <column-name>cust_addr</column-name> </attr-mapping> </psi-ri>
|
Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
|