Query Methods and EJB QL

Find and select methods for CMP (2.0) entity beans are defined using EJB QL. This query language, similar to SQL used in relational databases, is used to select one or more entity EJBs or entity bean fields. The WebLogic platform fully supports EJB QL 2.0 and offers a number of additional methods that can be used in conjunction with EJB QL.

Note. The EJB QL is used for all query methods, with the exception of findByPrimaryKey, which is automatically generated by the EJB container.

The topics in this section are:


Find Methods

A finder method is invoked by other EJBs or client applications on a CMP entity bean's local or remote home interface, and returns local or remote references to one or more instances of this entity bean that match the query. A find method can return a reference to a single entity instance, such as findByPrimaryKey, or to multiple entity instances returned as a java.util.Collection. Finder methods must start with the prefix find.

The following list shows common uses of EJB QL queries with find methods:

Note. The Finder Methods Sample allows you to run these and other EJB QL queries against a prefilled database table and examine the returned results. For more detailed information on EJB QL queries, see your favorite J2EE documentation.

Select Methods

A select method is defined using EJB QL and it can either return (local or remote) references to entity beans or values of an individual CMP field. A select method is not defined in the EJB's interfaces. In other words, it is a private method that can only be used internally by a CMP entity bean class. When returning object references, a select method can return a reference to a single entity instance, or to multiple entity instances which are returned as a java.util.Collection or java.util.Set. Select methods must start with the prefix ejbSelect.

The following list shows common uses of EJB QL queries with select methods:

Note. The Select Methods Sample allows you to run these and other EJB QL queries against a prefilled database table and examine the returned results.

Standard EJB QL Operators

EJB QL 2.0 defines a number of standard operators. Some of these, like IN, DISTINCT, and the use of '.' as a navigational operator (for instance, to access a EJB's CMP field) have been described above. Other operators include:

For more detailed information on EJB QL queries and the operators defined in this language, see the Finder and Select Methods Samples, or your favorite J2EE documentation.

WebLogic QL

The WebLogic platform offers an EJB QL extension, called WebLogic QL to run advanced queries. The following advanced query types are available:


Ordering Query Results

To order the results of a find or select query, you can used the WebLogic keyword ORDERBY. You can specify in ascending order (the default) or descending order, and sort on multiple fields.

The following query returns ItemBean instances, ordered by item name, that are produced by a US manufacturer:

SELECT OBJECT(i) from ManufacturerBean as o, IN(o.items) AS i WHERE o.usManufacturer = 1 ORDERBY i.itemname 

The following query for a select method returns all item names, ordered by price in descending order and by the quantity in stock in ascending order:

SELECT o.itemname from ItemsBean as o ORDERBY o.price DESC, o.quantityavailable ASC

Note. Because the actual ordering is done by the underlying DBMS, the exact order is database dependent.

Aggregate Functions

The following WebLogic aggregate functions are supported:

The following query returns all ItemsBean instances that are more expensive than the average price of all the items:

SELECT OBJECT(o) from ItemsBean as o WHERE o.price > (SELECT AVG(s.price) FROM ItemsBean AS s)

Returning Multiple CMP Fields

WebLogic QL supports select methods that, unlike the standard EJB QL, return the results of multi-field queries in the form of a java.sql.ResultSet. It is not possible to return object references as a ResultSet.

The following query returns the name and the quantity in stocks of all the items in the database:

SELECT o.itemname, o.quantityavailable from ItemsBean as o 

The following query, which combines this functionality with the aggregate and sorting capabilities, returns the sorted names of all manufacturers of the items, the number of items offered by a manufacturer, and the average price of these items. The ManufacturerBean and ItemsBean are defined to have an entity relation, such that each item has a manufacturer, and a manufacturer can produce multiple items. For each item, the ItemsBean's CMR field manufacturer stores a unique index to a manufacturer instance:

SELECT o.manufacturer.manufacturername, COUNT(o.itemnumber), AVG(o.price) from ItemsBean as o 
   GROUP BY o.manufacturer.manufacturername 
   ORDERBY o.manufacturer.manufacturername

Using Subqueries

WebLogic QL supports the use of subqueries. One example of such a query was already shown above:

SELECT OBJECT(o) from ItemsBean as o WHERE o.price > (SELECT AVG(s.price) FROM ItemsBean AS s)

This query returns all ItemsBean instances that are more expensive than the average price of all the items, the average price of the items first being computed in a subquery. Subqueries follow the same syntax rules as standard WebLogic QL queries. You must, however, make sure that unique identifiers are used in the subquery and outer query. For instance, in the above query identifier o is used for ItemsBean in the outer query, while identifier c is used for ItemsBean in the subquery.

Note. It is also possible to create nested subqueries. The nesting depth is limited by the underlying database's nesting capabilities.

Correlated and Uncorrelated SubQueries

The above query is an example of an uncorrelated subquery. That is, the subquery is evaluated independently of the containing query. In contrast, in correlated subqueries values drawn from the main query are used in the subquery. Correlated queries are usually more processing intensive because the subquery is re-evaluated for every possible value obtained from the main query.

The following correlated subquery returns the five cheapest ItemsBean instances:

SELECT OBJECT(mainItem) from ItemsBean as mainItem WHERE 5 > 
   (SELECT COUNT(subItem.itemname) FROM ItemsBean AS subItem 
           WHERE subItem.price < mainItem.price)

In this example the subquery evaluates for every mainItem, which is an instance of ItemsBean from the outer query, how many other items are less expensive, using the COUNT aggregate function. If there are less than 5 items cheaper than the items currently evaluated in the outer query, the outer query will include this instance in the returned collection.

Return Values

In the subquery examples shown above, the subquery returns a single value obtained through an aggregate function on a CMP field (COUNT and AVG are shown; other possible functions are MIN, MAX, and SUM as described above). The return value of a subquery can also be a single value for a CMP field, a set of values for a CMP field, a single object instance or multiple objects. The subquery cannot return values for multiple CMP fields.

When the subquery returns a set (of field values or objects), you must use one of these additional operators in the outer query to evaluate against the set:

The following query uses a correlated subquery to select all items in the subquery that are more expensive than the current item in the outer query. The outer query only selects an object when the set returned by the subquery is empty, using NOT EXISTS. In other words, this query returns the most expensive item(s):

SELECT OBJECT(mainItem) from ItemsBean as mainItem WHERE NOT EXISTS 
   (SELECT OBJECT(subItem) FROM ItemsBean as subItem  WHERE subItem.price > mainItem.price)

The following query uses a uncorrelated subquery that returns a set of CMP field values, and uses '> ALL' to select objects in the outer queries whose field value is larger than all the values in the set. Specifically this query uses a subquery to select the quantities in stock of all the items by a certain manufacturer, and the outer query returns all the object for which larger quantities are in stock:

SELECT OBJECT(mainItem) from ItemsBean as mainItem WHERE mainItem.quantityavailable > ALL 
   (SELECT subItem.quantityavailable from ItemsBean as subItem WHERE subItem.manufacturer.manufacturername = ?1)

Note. Queries using the ANY or ALL keyword do not properly run on PointBase.

Using Oracle Hints

To pass hints to an Oracle Query, you can use the WebLogic QL keyword SELECT_HINT and enter the quoted hint, as is shown in the following example:

SELECT OBJECT(o) from ItemsBean as o WHERE o.price > 20 SELECT_HINT '/*+ FULL(ItemsBean) */'

For more information on hints, see your favorite Oracle documentation.

Related Topics

How Do I: Add a Finder Method to an Entity Bean?

Finder Methods Sample

@ejbgen:finder Annotation

How Do I: Add a Select Method to an Entity Bean?

Select Methods Sample

@ejbgen:select Annotation