Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide 10g Release 3 (10.1.3) B14428-02 |
|
![]() Previous |
![]() Next |
This chapter describes:
For more information, see:
Note: For an example OC4J EJB QL application, see:http://www.oracle.com/technology/sample_code/tech/java/ejb_corba/ejbql/Readme.html . |
The following procedure describes how to implement an EJB 2.1 EJB QL finder method.
Before implementing a finder method, consider the predefined and default finders that OC4J provides (see "Predefined TopLink Finders" and "Default TopLink Finders").
For more information, see "Understanding Finder Methods".
Define the finder method in the home interface (see "Using Java").
If you are exposing only predefined or default finders (see "Predefined TopLink Finders" and "Default TopLink Finders"), you are done.
If you are exposing a custom finder, proceed to step 2.
Configure the ejb-jar.xml
file (see "Using Deployment XML").
Note: You can do this manually as described here or you can use the TopLink Workbench (see "Using TopLink Workbench") to automate this step and to take advantage of advanced TopLink finder configuration. |
For each entity bean that you plan to reference in your EJB QL query, configure the <entity>
element <abstract-schema-name>
sub-element.
The <abstract-schema-name>
sub-element defines the name that identifies the entity bean in the EJB QL statement. For example, given an entity bean class named EmpBean
, if you define its <abstract-schema-name>
as Employee
, then in your EJB QL statement, when you use the name Employee
, the container will map that name to the EmpBean
entity bean (see Example 16-2).
Define a <query>
element for each finder method that you exposed in the EJB home interface.
Note: Do not define a<query> element for predefined or default finders, including findByPrimaryKey . |
The <query>
element has the following sub-elements:
<description>
: optional explanatory text
<query-method>
: describes the finder method and includes the following sub-elements:
<method-name>
: identifies the finder method. Configure this element with the same method name as defined in the home interface.
<method-params>
: if the finder takes arguments, define this element and for each argument, define a <method-param>
sub-element that gives the argument type. The type and order of arguments must match that specified by this finder's signature.
<ejb-ql>
: contains the EJB QL statement for this method.
You can define a full query or just the conditional statement (the WHERE
clause).
If the finder method returns a Collection
, to ensure that no duplicates are returned, specify the DISTINCT
keyword in the EJB QL statement.
To use parameters (as specified by <method-params>
) in your EJB QL, use the <
integer
>?
notation where <
integer
>
begins with 1. For example, ?1
corresponds to the first <method-param>
element, ?2
corresponds to the second <method-param>
element, and so on (see the findAllByEmpName
finder in Example 16-2).
To define an EJB QL statement that relates this EJB with another, you must first define the appropriate container-managed relationship. The findByDeptNo finder in Example 16-2 requires the relationship with <ejb-relation-name>
Employee-Departments
. For more information, see "Configuring an EJB 2.1 CMP Entity Bean Container-Managed Relationship Field".
Example 16-1 shows a remote home interface called EmpBeanHome
.
Example 16-1 Finder Methods in an EJB 2.1 CMP Entity Bean Remote Home Interface
package cmpapp; import javax.ejb.*; import java.rmi.*; public interface EmpBeanHome extends EJBHome { public EmpBean create(Integer empNo, String empName) throws CreateException; /** * Finder methods. These are implemented by the container. We can * customize the functionality of these methods in the deployment * descriptor through EJB-QL. **/ // Predefined Finders: <query> element in ejb-jar.xml not required public Topic findByPrimaryKey(Integer key) throws FinderException; public Collection findManyBySQL(String sql, Vector args) throws FinderException // Default Finder: <query> element in ejb-jar.xml not required public Topic findByEmpNo(Integer empNo) throws FinderException; // Custom Finders: <query> element is required in ejb-jar.xml public Collection findAllRegionalEmployees(Integer empNo) throws FinderException; public Collection findAllByEmpName(String empName) throws FinderException; public Topic findByDeptNo(Integer deptNo) thorws FinderException public Collection findAllBetweenSalaries(Integer lowSalary, Integer highSalary); }
Example 16-2 shows the ejb-jar.xml
for the finders declared in the home interface that Example 16-1 shows.
Example 16-2 ejb-jar.xml For EJB 2.1 EJB QL Finders
<enterprise-beans> <entity> <display-name>EmpBean</display-name> <ejb-name>EmpBean</ejb-name> ... <abstract-schema-name>Employee</abstract-schema-name> <cmp-field><field-name>empNo</field-name></cmp-field> <cmp-field><field-name>empName</field-name></cmp-field> <cmp-field><field-name>salary</field-name></cmp-field> <primkey-field>empNo</primkey-field> <prim-key-class>java.lang.Integer</prim-key-class> ... <query> <description>Regional employees have empNo greater than 10000</description> <query-method> <method-name>findAllRegionalEmployees</method-name> <method-params></method-params> </query-method><ejb-ql>
SELECT OBJECT(e) FROM Employee e WHERE e.empNo > 10000</ejb-ql> </query> <query> <description>Find all employees with the given name</description> <query-method> <method-name>findAllByEmpName</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql>SELECT OBJECT(e) FROM Employee e WHERE e.empName = ?1</ejb-ql> </query> <query> <description>Relationship finder</description> <query-method> <method-name>findByDeptNo</method-name> <method-params> <method-param>java.lang.Integer</method-param> </method-params> </query-method> <ejb-ql> SELECT DISTINCT OBJECT(e) From Employee e, IN (e.dept) AS d WHERE d.deptNo = ?1 </ejb-ql> </query> <query> <description>Find all employees with salaries in the given range</description> <query-method> <method-name>findAllBetweenSalaries</method-name> <method-params> <method-param>java.lang.Integer</method-param> <method-param>java.lang.Integer</method-param> </method-params> </query-method> <ejb-ql>SELECT OBJECT (e) FROM Employee e WHERE e.salary BETWEEN ?1 and ?2
</ejb-ql> </query> ... </entity> ... </enterprise-beans> <relationships> <ejb-relation> <ejb-relation-name>Employee-Departments</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Employee-has-Departments</ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>Department</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>dept</cmr-field-name> <cmr-field-type>java.lang.Integer</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relation> ... <relationships>
Using the TopLink Workbench, you can configure your toplink-ejb-jar.xml
file with a custom TopLink finder and update your ejb-jar.xml
file.
For more information, see:
"Creating a Finder" in the Oracle TopLink Developer's Guide
"Configuring Named Queries at the Descriptor Level" in the Oracle TopLink Developer's Guide
The following procedure describes how to implement an EJB 2.1 EJB QL select method.
For more information, see "Understanding Select Methods".
Define the select method as a public
, abstract
method of your abstract entity bean class (see "Using Java").
In the ejb-jar.xml
file (see "Using Deployment XML"):
For each entity bean that you plan to reference in your EJB QL query, configure the <entity>
element <abstract-schema-name>
sub-element.
The <abstract-schema-name>
sub-element defines the name that identifies the entity bean in the EJB QL statement. For example, given an entity bean class named EmpBean: if you define your <abstract-schema-name>
as Employee
, then in your EJB QL statement, when you use the name Employee
, the container will map that name to the EmpBean
entity bean ().
Define a <query>
element for each select method that you exposed in the EJB home interface.
You can define a full query or just the conditional statement (the WHERE
clause).
If the select method returns a Collection
, to ensure that no duplicates are returned, specify the DISTINCT
keyword in the EJB QL statement.
The <query>
element has two main elements:
If the query returns a Collection
of CMR values, decide on the interface type you want returned:
The ejb-jar.xml
file <result-type-mapping>
element determines the return type for select methods. Set the flag to Remote
to return EJBObjects
; set it to Local
to return EJBLocalObjects
.
Example 16-3 shows an abstract entity bean class called UserAccountBean
for an EJB 2.1 CMP entity bean with select methods.
Example 16-3 EJB 2.1 CMP Entity Bean Implementation With Select Methods
package oracle.otnsamples.ejbql; import javax.ejb.*; import java.util.*; public abstract class UserAccountBean implements EntityBean { /* ---------------------------------------- * Non-Persistent State * -------------------------------------- */ protected EntityContext ctx; /* ------------------------------------------------------ * Begin abstract get/set methods. Container-managed persistence fields are specified in the ejb-jar.xml deployment descriptor. * ------------------------------------------------------- */ public abstract Long getAccountnumber(); public abstract void setAccountnumber(Long newAccountnumber); public abstract Long getCreditlimit(); public abstract void setCreditlimit(Long newCreditlimit); /** * Select methods. These are implemented by the container. We can * customize the functionality of these methods in the deployment * descriptor through EJB-QL. * * These methods are NOT exposed in the bean's home interface. **/ public abstract Long ejbSelectCreditLimit(Long accountnumber) throws FinderException; public abstract Collection ejbSelectByTopAccounts() throws FinderException; /* ------------------------------------------------------ * Begin buisness logic methods that use select methods. * * These methods are exposed in the bean's home interfaces. * ------------------------------------------------------- */ /** * Method to perform post-processing operations on all the * UserAccounts retrieved by calling ejbSelectByTopAccounts. This * method further process the retrieved UserAccounts and checks * for the Accounts with TopCredits (credit limits) and returns the * collection of input number of UserAccounts. * Post-processing information within the EJB container itself * has the following two advantages: * 1) It improves performance as the application can now leverage * the advantage of the vast resources available to the server. * 2) The data-processing code should go into the business logic * and not the Web-tier. This helps in maintaining the code. * Consider these advantages when deciding between ejbFind and * ejbSelect methods. * * @return Collection of <input number of> Top (credited) UserAccounts */ public Collection ejbHomeTopAccounts(String accountNumbers) throws FinderException { // Invoke the ejbSelect method and get all the Account Information. Collection collection = this.ejbSelectByTopAccounts(); ... return topAccounts; } /** * Method to call ejbSelectCreditLimit and return the credit limit value * for the input accountnumber without post-processing. * Please note that this method returns a Long instead of a collection * that is returned normally by the EJB container. This is a major * advantage of ejbSelect methods. Using these methods, we can return * an object from 'within' the CMP instead of 'the' CMP. This way, the * application uses the server and the EJB container resources more * effeciently. * * @return Credit Limit of the input UserAccount */ public Long ejbHomeCreditLimit(Long accountnumber) throws FinderException { // Return the Credit Limit of the specified Account return this.ejbSelectCreditLimit(accountnumber); } ... }
Example 16-4 shows the ejb-jar.xml
for the select methods defined in the abstract entity bean class that Example 16-3 shows.
Example 16-4 ejb-jar.xml For EJB 2.1 EJB QL Select Methods
<enterprise-beans> <entity> <description>Entity Bean ( CMP )</description> <display-name>UserAccount</display-name> <ejb-name>UserAccount</ejb-name> <local-home>oracle.otnsamples.ejbql.UserAccountLocalHome</local-home> <local>oracle.otnsamples.ejbql.UserAccount</local> <ejb-class>oracle.otnsamples.ejbql.UserAccountBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.Long</prim-key-class> <abstract-schema-name>UserAccount</abstract-schema-name> <cmp-field> <field-name>accountnumber</field-name> </cmp-field> <cmp-field> <field-name>creditlimit</field-name> </cmp-field> <primkey-field>accountnumber</primkey-field> <query> <description>Selects all accounts and post-process to find top accounts</description> <query-method> <method-name>ejbSelectByTopAccounts
</method-name> </query-method> <ejb-ql>select distinct object(ua) from UserAccount ua</ejb-ql> </query> <query> <description>Retrieves the Credit Limit for an Account</description> <query-method> <method-name>ejbSelectCreditLimit
</method-name> <method-params> <method-param>java.lang.Long</method-param> </method-params> </query-method> <ejb-ql> select ua.creditlimit from UserAccount ua where ua.accountnumber = ?1 </ejb-ql> </query> </entity> </enterprise-beans>
Using the TopLink Workbench, you can configure your toplink-ejb-jar.xml
file with a custom TopLink ejbSelect and update your ejb-jar.xml
file.
For more information, see: "Creating a Finder" in the Oracle TopLink Developer's Guide
Although EJB 2.1 does not support square root, date, time, and timestamp types, OC4J provides proprietary EJB QL extensions to support these types in EJB 2.1, as follows:
SQRT
(v): Both the double primitive type and the java.lang.Double
types are supported for arguments (see Example 16-5).
You can use the following date, time, and timestamp types in an EJB QL binary expression, such as equality expressions:
java.util.Date
(see Example 16-6
java.sql.Date
(see Example 16-7)
java.sql.Time
(see Example 16-8)
java.sql.Timestamp
(see Example 16-9)
Note: These types are fully supported in EJB 3.0 EJB QL. |
Example 16-5 Using the EJB 2.1 EJB QL Extension for SQRT
<query> <query-method> <method-name>ejbSelectDoubleTypeSqrt</method-name> <method-params> <method-param>double</method-param> </method-params> </query-method> <result-type-mapping>Remote</result-type-mapping> <ejb-ql> SELECT OBJECT(a) FROM Dept a WHERE a.deptDoubleType = SQRT(?1) </ejb-ql> </query>
Example 16-6 Using the EJB 2.1 EJB QL Extension for java.util.Date
<query>
<query-method>
<method-name>ejbSelectDate</method-name>
<method-params>
<method-param>java.util.Date</method-param>
</method-params>
</query-method>
<result-type-mapping>Remote</result-type-mapping>
<ejb-ql>
SELECT OBJECT(a) FROM Dept a WHERE a.deptDate = ?1
</ejb-ql>
</query>
Example 16-7 Using the EJB 2.1 EJB QL Extension for java.sql.Date
<query>
<query-method>
<method-name>ejbSelectSqlDate</method-name>
<method-params>
<method-param>java.sql.Date</method-param>
</method-params>
</query-method>
<result-type-mapping>Remote</result-type-mapping>
<ejb-ql>
SELECT OBJECT(a) FROM Dept a WHERE a.deptSqlDate = ?1
</ejb-ql>
</query>
Example 16-8 Using the EJB 2.1 EJB QL Extension for java.sql.Time
<query>
<query-method>
<method-name>findByTimestamp</method-name>
<method-params>
<method-param>java.sql.Time</method-param>
</method-params>
</query-method>
<result-type-mapping>Remote</result-type-mapping>
<ejb-ql>
SELECT OBJECT(a) FROM Dept a WHERE a.deptTime = ?1
</ejb-ql>
</query>
Example 16-9 Using the EJB 2.1 EJB QL Extension for java.sql.Timestamp
<query>
<query-method>
<method-name>findByTimestamp</method-name>
<method-params>
<method-param>java.sql.Timestamp</method-param>
</method-params>
</query-method>
<result-type-mapping>Remote</result-type-mapping>
<ejb-ql>
SELECT OBJECT(a) FROM Dept a WHERE a.deptTimestamp = ?1
</ejb-ql>
</query>