0% found this document useful (0 votes)
15 views

Advanced Ejb QL

This document provides examples of advanced EJB QL queries, including: - Using the "IN" keyword to access collections in the FROM clause and in WHERE clauses to test against lists. - Traversing multiple relationships in a query to find objects related through different paths. - Using objects instead of values as arguments in queries. - Using LIKE to search for patterns, with examples searching course descriptions and IDs. The examples are based on entities in a sample university registration application, including Person, Course, Student, Instructor and their relationships.
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Advanced Ejb QL

This document provides examples of advanced EJB QL queries, including: - Using the "IN" keyword to access collections in the FROM clause and in WHERE clauses to test against lists. - Traversing multiple relationships in a query to find objects related through different paths. - Using objects instead of values as arguments in queries. - Using LIKE to search for patterns, with examples searching course descriptions and IDs. The examples are based on entities in a sample university registration application, including Person, Course, Student, Instructor and their relationships.
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 5

ADVANCED EJB QL

The August, 2003 issue of the Enterprise Java Technologies Tech Tips provided introductory examples
of using Enterprise JavaBeans Query Language (EJB QL). Specifically, it showed how to use EJB QL
to create finder methods for entity beans in EJB version 2.0 and above. This month's tips provide more
examples of using EJB QL. The first tip provides examples of more advanced EJB QL, and the second
tip shows how to write and use EJB select methods.

SQL vs. EJB QL: Relational and Object Query Languages

EJB QL is an SQL-like query language. EJB QL queries are, however, somewhat different from
relational SQL. SQL queries find data using a relational model. By contrast, EJB QL queries find data
using the "abstract schema" of the enterprise beans in your application. So, instead of using SQL to
query tables, rows, and columns, you use EJB QL to query enterprise beans, their persistent state, and
their relationships. The result of an SQL query is a set of rows, with each row having the same
sequence of columns. The result of an EJB QL query is either a collection of entity objects of a given
type, a single entity object, or a collection of values retrieved from CMP (container-managed
persistence) fields.

Typically, entity beans are stored in a relational database. EJB QL is designed so that the EJB container
can map EJB QL queries directly to SQL. The resulting SQL queries are then executed against the
relational database to retrieve the entity bean data.

Relational and object models differ in how they model relationships. A relational model uses foreign
keys and joins to represent relationships. An object model uses a named relationship from one object
type to another. Many of the joins in WHERE clauses of relational SQL queries join foreign keys to one
another. Instead of joining primary keys in a WHERE clause, EJB QL queries use the "." operator and
CMR field names to traverse relationships.

Understanding the data model of your application's enterprise beans is crucial to writing effective EJB
QL queries. The following section explains the data model of the enterprise beans in this month's
sample code.

Sample Code Data Model

The sample code for this month's tip is a Web application that implements a small university course
registration system. A servlet (PersonServlet) uses several enterprise beans to implement searches on
student registration data.
The sample code servlet accesses a data model consisting of the following entities:

 A Person entity represents a person in the system. It has two 1-to-1 relationships with Address
("workAddress" and "homeAddress"), and a 1-to-many relationship with Phone ("phones"). A
Person's primary key is its "id" field.

 A Course entity represents a course offered by the university. It has a many-to-many


relationship with Instructor ("instructors"), and a many-to-many relationship with Student
("students"). Its primary key is its "id" field.
 A Phone entity represents a phone number for a single Person. It has no relationships to other
entities.
 An Address entity represents an address for a single Person. It has no relationships to other
entities.
 A Student represents a student in the university. It has a 1-to-1 relationship to Person
("studentPerson"), and a many-to-many relationship with Course ("coursesEnrolledIn").
 An Instructor represents an instructor in the university. It has a 1-to-1 relationship to Person
("instructorPerson"), and a many-to-many relationship with Course ("coursesTaught").

Notice that in this data model, some relationships are unidirectional. For example, the relationship
instructorPerson indicates the Person associated with an Instructor, but there's no way (using
CMR fields) to access an Instructor associated with a Person.

Now that you understand the underlying data model, you can write EJB QL queries to find object
instances. You can execute the example queries in the following sections by first deploying the sample
application in your J2EE server, and then activating the appropriate link or form in the application's
index.html page. For instructions on how to deploy and run the sample application, see the section
"Running the Sample Code."

Using "IN" to Access CMR Collections In A FROM Clause


The EJB QL keyword "IN" has two uses. In the first case, the IN() keyword allows the programmer to
use CMR collections in a query's FROM clause. The example in the sample code is the query for the
finder method CourseLocalHome.findByPersonEnrolled. Given a PersonLocal interface instance
as an argument, the following query returns a collection of the courses in which this Person (as a
Student) is enrolled:

SELECT OBJECT(c)
FROM Person AS p, IN(p.student.coursesEnrolledIn) AS c
WHERE p = ?1

The code in the PersonServlet class that uses the associated finder method looks like this:

String person_id = req.getParameter("ID");


PersonLocal person =
Util.findPersonLocalHome().findByPrimaryKey(person_id);
Collection courses =
Util.findCourseLocalHome().findByPersonEnrolled(person);

In the FROM clause of the query, the expression IN(p.student.coursesEnrolledIn) traverses the
relationship "student" from Person to Student, and then traverses the relationship
"coursesEnrolledIn" from Student to Course. The clause "AS c" defines an "identification
variable" that can be used elsewhere in the clause to represent the results of the traversal.

Executing this method prints a list of the classes in which an individual Person is enrolled. You can
execute this query by entering a valid Person ID (obtained from one of the other examples) in the form
titled "Find all courses in which a particular Person is enrolled".

Using IN in WHERE Clauses

Another use of the "IN" keyword is to test the contents of a CMP field against any of a list of strings in
a WHERE clause. In the sample code, an Instructor has a type string, which is one of
('ResearchFellow', 'Adjunct', 'Associate', 'Assistant', 'Full', or 'Emeritus'). In this University,
research fellows and emeritus professors are considered instructors, but are never assigned teaching
positions. The following query identifies such instructors:

SELECT OBJECT(i)
FROM Instructor AS i
WHERE i.type IN ('ResearchFellow', 'Emeritus')

This query is used by the finder method InstructorLocalHome.findNonTeaching(). The


PersonServlet in the sample code uses the method like this:

ilh = Util.findInstructorLocalHome();
Collection nonteachinginstructors =
ilh.findNonTeaching();

To execute this query, select the link titled "List all non-teaching instructors (Emeritus and Research
Fellows)" on the main page of the sample application.
Traversing Multiple Relationships

You can use more than one relationship in an EJB QL query. Remember that a Person can be both a
Student and an Instructor. Finder method PersonLocalHome.findStudentInstructors identifies
Person objects that have both Instructor and Student objects. The method uses the following query:

SELECT OBJECT(p) FROM Person AS p,


Instructor i, Student s
WHERE i.instructorPerson = p AND
s.studentPerson = p

Notice that the items in the WHERE clause being compared to one another are objects, not values (such
as primary keys). In other words, this query selects all Persons for whom an Instructor exists and a
Student exists. Persons missing either an Instructor or a Student do not meet the conditions of the
WHERE clause, and are therefore excluded from the result set.

You can execute this query by clicking the link "Find all Persons who are both Instructor and Student"
on the main page of the sample application.

Queries With Objects As Arguments - findByPersonEnrolled

In the other examples shown in this tip (and in last month's tip), arguments to queries have been values,
such as "WHERE p.id = ?1". But take another look at the query for the finder findByPersonEnrolled
(already discussed above):

SELECT OBJECT(c)
FROM Person AS p, IN(p.student.coursesEnrolledIn) AS c
WHERE p = ?1

Notice that the parameter to the query is an object (of type Person), not a primitive value. This is
perfectly legal usage. In such cases, the parameter passed to the finder method is the component
interface type, as shown below:

PersonLocal person =
Util.findPersonLocalHome().findByPrimaryKey(person_id);
Collection courses =
Util.findCourseLocalHome().findByPersonEnrolled(person);

As mentioned earlier, you can execute this query in the sample application by submitting the form
titled "Find all courses in which a particular Person is enrolled".

Searching With Patterns Using LIKE

The LIKE keyword, used in WHERE clauses, works in EJB QL just as it does in SQL. LIKE provides
matching of a string attribute value against a very simple pattern. For example, the sample code method
CourseLocalHome.findIntroductoryCourses is implemented by the following EJB QL query:

SELECT OBJECT(c)
FROM Course AS c
WHERE c.description LIKE '%INTRODUCT%' OR c.id LIKE '1__'

The application defines an introductory course as any course whose description contains the string
'INTRODUCT', or any course with an 3-digit ID number between 100 and 199. The query performs the
search using two LIKE clauses. The pattern string for a LIKE clause has two special characters. The
special character % matches any string (including an empty string). The special character _ matches any
single character. (Note that the pattern %INTRODUCT% matches strings beginning with INTRODUCT,
because the first % matches the empty string.) Every other character in the string matches only itself.

To execute method findIntroductoryCourses in the sample application, click the link "List
introductory courses" on the application's main page.

To match a % or a _ in an attribute value, you must define and use an escape character. The escape
character is defined using the ESCAPE keyword in the LIKE clause, for example:

SELECT OBJECT(Mortgage) AS m
WHERE m.rate LIKE '3.%\%' ESCAPE '\'

In the expression 3.%\% above, the characters 3, and . match themselves, the first % matches any
number of characters, and \% matches a percent sign.

You might also like