The Query Methods

There are two main types of query methods: find methods and select methods. These are discussed in the following sections.

Find Methods

Find methods are invoked by EJB clients (applications or beans) in order to locate and obtain the remote or local EJB object references to specific entity beans. For example, you might call the findByPrimaryKey() method on the Customer EJB’s home interface to obtain a reference to a specific Customer bean.

Find methods are always declared in the local and remote home interfaces of an entity bean. As you have already learned, every home interface must define a findByPrimaryKey() method; this is a type of single-entity find method. Specifying a single remote or local return type for a find method indicates that the method locates only one bean. findByPrimaryKey() obviously returns only one remote reference, because there is a one-to-one relationship between a primary key’s value and an entity. Other single-entity find methods can also be declared. For example, in the following code segment the Customer EJB declares several single-entity find methods, each of which supports a different query:

public interface CustomerHomeRemote extends javax.ejb.EJBHome {
    public CustomerRemote findByPrimaryKey(Integer primaryKey)
        throws javax.ejb.FinderException, java.rmi.RemoteException;

    public CustomerRemote findByName(String lastName, String firstName)
        throws javax.ejb.FinderException, java.rmi.RemoteException;

    public CustomerRemote findBySSN(String socialSecurityNumber)
        throws javax.ejb.FinderException, java.rmi.RemoteException;
}

Bean developers can also define multi-entity find methods, which return a collection of EJB objects. The following listing shows a couple of multi-entity find methods:

public interface CustomerHomeLocal extends javax.ejb.EJBLocalHome {
    public CustomerLocal findByPrimaryKey(Integer primaryKey)
        throws javax.ejb.FinderException;

    public Collection findByCity(String city,String state)
        throws javax.ejb.FinderException;

    public Collection findByGoodCredit()
        throws javax.ejb.FinderException;
}

To return several references from a find method, you must use a java.util.Collection type.[30] A find method that uses this return type may have duplicates. To avoid duplicates, you can use the keyword DISTINCT in the EJB QL statement associated with the find method. This technique is explained in more detail in Section 8.3.4 later in this chapter. Multi-entity finds return an empty Collection if no matching beans are found.

Enterprise JavaBeans specifies that all query methods (find or select) must be declared as throwing the javax.ejb.FinderException . Find methods that return a single remote reference throw a FinderException if an application error occurs and a javax.ejb. ObjectNotFoundException if a matching bean cannot be found. The ObjectNotFoundException is a subtype of FinderException and is thrown only by single-entity find methods.

Every find method declared in the local or remote home interface of a CMP 2.0 entity bean must have a matching query declaration in the bean’s deployment descriptor. The following snippet from the Customer EJB’s deployment descriptor shows declarations of two find methods, findByName() and findByGoodCredit() , from the earlier examples:

               <query>
    <query-method>
        <method-name>findByName</method-name>
        <method-params>
            <method-param>java.lang.String</method-param>
            <method-param>java.lang.String</method-param>
        </method-params>
    </query-method>
    <ejb-ql>
        SELECT OBJECT(c) FROM Customer c 
        WHERE c.lastName = ?1 AND c.firstName = ?2
    </ejb-ql>
</query>
               <query>
    <query-method>
        <method-name>findByGoodCredit</method-name>
        <method-params/>
    </query-method>
    <ejb-ql>
        SELECT OBJECT(c) FROM Customer c
        WHERE c.hasGoodCredit = TRUE
    </ejb-ql>
</query>

The query elements in the deployment descriptor allow the bean developer to associate EJB QL statements with specific find methods. When the bean is deployed, the container attempts to match the find method declared in each of the query elements with find methods in the entity bean’s home interfaces. This is done by matching the values of the <method-name> and <method-params> elements with method names and parameter types (ordering is important) in the home interfaces.

When two find methods in the local and remote home interfaces have the same method name and parameters, the query declaration will apply to both of the methods. The container will return the proper type for each query method: the remote home will return one or more remote EJB objects, and the local home will return one or more local EJB objects. This allows you to define the behavior of both the local and remote home find methods using a single <query> element, which is convenient if you want local clients to have access to the same find methods as remote clients.

The <ejb-ql> element specifies the EJB QL statement for a specific find method. You may have noticed that EJB QL statements can use input parameters (e.g., ?1, ?2, ... ?n), which are mapped to the <method-param> of the find method, as well as literals (e.g., TRUE). The use of input parameters and literals will be discussed in more detail throughout this chapter.

With the exception of findByPrimaryKey() methods, all single-entity and multi-entity find methods must be declared in <query> elements in the deployment descriptor. Query declarations for findByPrimaryKey() methods are not necessary and, in fact, are forbidden. It’s obvious what this method should do, and you may not try to change its behavior.

Select Methods

Select methods are similar to find methods, but they are more versatile and can be used only internally, by the bean class. In other words, select methods are private query methods; they are not exposed to an entity bean’s clients through the home interfaces.

Another difference between the select and find methods is the transaction context under which they execute. The select method executes in the transaction context of the business or callback method that is using it, while the find methods execute according to their own transaction attributes, as specified by the bean provider.

Select methods are declared as abstract methods using the naming convention ejbSelect< METHOD-NAME >. The following code shows four select methods declared in the AddressBean class:

public class AddressBean implements javax.ejb.EntityBean {
    ...
    public abstract String ejbSelectCity(AddressLocal addr)
        throws FinderException;
    
    public abstract Set ejbSelectZipCodes(String state)
        throws FinderException;

    public abstract Collection ejbSelectAll()
        throws FinderException;

    public abstract CustomerLocal ejbSelectCustomer(AddressLocal addr)
        throws FinderException;
    ...

Select methods can return the values of CMP fields. The ejbSelectCity(AddressLocal addr) method, for example, returns a single String value, the name of the city referenced by the Address EJBs.

To return several references from a select method, you must declare the return type to be either a java.util.Collection or java.util.Set. [31] A select method that uses a Set return type will not have duplicate values, while a Collection return type may have duplicates. Multi-entity selects return an empty Collection or Set if no matching beans are found. The ejbSelectZipCodes() method returns a java.util.Set of String values: a unique collection of all the Zip Codes declared for the Address EJBs for a specific state.

Like find methods, select methods can declare zero or more arguments, which are used to limit the scope of the query. The ejbSelectZipCodes() and ejbSelectCustomer() methods both declare arguments used to limit the scope of the results. These arguments are used as input parameters in the EJB QL statements assigned to the select methods.

Select methods can return local or remote EJB objects. For single-entity select methods, the type is determined by the return type of the ejbSelect() method. The ejbSelectCustomer() method, for example, returns a local EJB object, the CustomerLocal. This method could easily have been defined to return a remote EJB object by changing the return type to the Customer bean’s remote interface (CustomerRemote). Multi-entity select methods, which return a collection of EJB objects, return local EJB objects by default. However, the bean provider can override this default behavior using a special element, the <result-type-mapping> element, in the select method’s <query> element.

The following portion of an XML deployment descriptor declares two of the select methods from the above example. Notice that they are exactly the same as the find method declarations. Find and select methods are declared in the same part of the deployment descriptor, within a <query> element inside an <entity> element:

               <query>
    <query-method>
        <method-name>ejbSelectZipCodes</method-name>
        <method-params>
            <method-param>java.lang.String</method-param>
</method-params>
    </query-method>
    <ejb-ql>
        SELECT a.homeAddress.zip FROM Address AS a
        WHERE a.homeAddress.state = ?1
    </ejb-ql>
</query>
<query>
    <query-method>
        <method-name>ejbSelectAll</method-name>
        <method-params/>    
    </query-method>
    <result-type-mapping>Remote</result-type-mapping>
    <ejb-ql>
        SELECT OBJECT(a) FROM Address AS a
    </ejb-ql>
</query>

The name given in each <method-name> element must match one of the ejbSelect< METHOD-NAME >() methods defined in the bean class. This is different from find methods of CMP 2.0 beans, which do not have a corresponding ejbFind method in the bean class. For find methods, we use the method name in the local or remote home interface. Select methods, on the other hand, are not declared in the local or remote home interface, so we use the ejbSelect() method name in the bean class.

Select methods can return local or remote EJB objects. The default is to return local EJB object types for both single-entity and multi-entity select methods. However, the bean provider can override this default behavior using a special element, <result-type-mapping>, in the select method’s <query> element. The value of <result-type-mapping> can be either Remote or Local. A value of Local indicates that the select method should return local EJB objects; Remote indicates remote EJB objects. If the <result-type-mapping> element is not declared, the default is Local. For single-entity select, the actual return type of the ejbSelect() method must match the <result-type-mapping>. For example, if a single-entity ejbSelect() method returns an EJBObject type, the <result-type-mapping> must be Remote. In the previous example, the <result-type-mapping> in the <query> element for the ejbSelectAll() method is declared as Remote, which means the query should return remote EJB object types (i.e., remote references to the Address EJB).[32]

Select methods are not limited to the context of any specific entity bean. They can be used to query across all the entity beans declared in the same deployment descriptor. Select methods may be used by the bean class from its ejbHome() methods, from any business methods, or from the ejbLoad() and ejbStore() methods. In most cases, select methods will be called from ejbHome() or from business methods in the bean class. The ejbHome(), ejbLoad(), and ejbStore() methods are covered in more detail in Chapter 11.

The most important thing to remember about select methods is that while they can do anything find methods can and more, they can be used only by the entity bean class that declares them, not by the entity bean’s clients.



[30] In CMP 2.0, java.util.Collection is the only collection type supported for multi-entity find methods. EJB 1.1 CMP and EJB 2.0 BMP also support java.util.Enumeration.

[31] Other collection types, such as java.util.List and java.util.Map, may be added in future versions.

[32] This is illustrative. As a developer, it is unlikely (although possible) that you would define a remote interface for the Address EJB, because it is too fine-grained for use by remote clients.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset