Introducing CMP Finder methods.

Finder methods find entities in the database according to criteria specified in the deployment descriptor. This enables you to search and retrieve your data without using JDBC and writing SQL in your code.

Queries associated with finder methods are specified in the deployment descriptor using EJB 2.0's new query language, EJB-QL. Although EJB-QL is a restriction of SQL, it is powerful enough for typical bean selection. The power of EJB-QL will become more apparent in later examples with the introduction of CMR, Container Managed Relations between entities.

The following example uses a simple finder method to find all houses in the Hogwarts Wizard Boarding School. It uses this schema:

    DROP TABLE find_courses;
    CREATE TABLE find_courses (
      course_id VARCHAR(250) NOT NULL,
      instructor VARCHAR(250),

      PRIMARY KEY(course_id)
    );

    INSERT INTO find_courses VALUES('Potions', 'Severus Snape');
    INSERT INTO find_courses VALUES('Transfiguration', 'Minerva McGonagall');
    INSERT INTO find_courses VALUES('Defense Against the Dark Arts', 'Remus Lupin');
    

Defining the finder method in the Home Interface

Finder methods are declared in the Home Interface. They must begin with the word 'find'. You can define as many finder methods as you want, but you must define at least the findByPrimaryKey(...) method that we saw in the first example.

Finder methods can be of one of the following three types:

  • java.util.Collection if you want to be able to retreive any number of matches (including 0). The returned Collection may contain duplicates. The findAll() method in this package's Home Interface is an example of such a method.
  • java.util.Set is used just like a Collection, but the Container makes sure that it contains no duplicates.
  • If you want to retreive only one matching entity, the returntype of the finder method must equal that of the Local Interface. The findCourseByInstructor(String) method in this Bean's Home Interface is an example of such a method.

    If your finder method returns a Local Interface type, it may throw a FinderException in case it could not find a match. Collection and Map types simply return the empty set when they can't find any matches.

    In this example, we have declared the findCourseByInstructor(String) finder method:

    
      public Course findCourseByInstructor(String instructorName)
        throws FinderException;
      

    Defining the finder method in the deployment descriptor

    In addition to the method declaration, we also need to define a <query> section in the deployment descriptor for each finder method. The findCourseByInstructor method in this example is defined in cmp-find.ejb like this:

     <query>
      <query-method>
       <method-name>findCourseByInstructor</method-name>
      <method-params>
      <method-param>java.lang.String</method-param>
       </method-params>
      </query-method>
     
      <ejb-ql>
       <![CDATA[SELECT o FROM find_courses o WHERE o.instructor = ?1]]>
      </ejb-ql>
     </query>

    Note that the method parameters specified in the <query> section need to match the amount and types of parameters specified in the Home Interface.

    The actual query is defined in the <ejb-ql> element above.

  • ?1 is a variable and correspondes to the first parameter passed to the method.
  • The FROM section sets up the domain from which we can select entities in the SELECT part of the query.

    For a more comlete guide to EJB-QL, check out the example.cmp.ejbql example.