EJB-QL is the EJB 2.0 query language. It is similar to SQL, but has the advantage that it can be applied to a variety of different backing store types. For relational databases, Resin-CMP compiles EJB-QL to SQL statements at deploytime.
In addition to being backing-store independent, EJB-QL allows you to reference your CMP and CMR fields inside queries. This means you're writing queries at an object-oriented level.
For our example, we have the following relationships:
[COURSE](n)----(n)[STUDENT]
(1) (n)
| \
| \
(1) (1)
[TEACHER] [HOUSE]
Basics
An EJB-QL query is composed of, at most, three clauses:
SELECT
clauseFROM
clauseWHERE
clause (optional)The FROM
clause defines the domain from which elements can be
chosen in the SELECT
clause:
SELECT house FROM ejbql_house AS house
ejbql_house
is the abstract schema type (that is, the table) that
stores our house entities. In the FROM
clause, we assign this
abstract schema type the name house
(house
is an
identification variable). Now that we have declared the domain of the query,
we can select house
with the SELECT
clause. Note that
this query can evaluate to a Collection of Houses or just one House, depending
on the return type that you have assigned to your finder method.
Navigating with CMR fields
Recall that CMR fields are virtual fields, and that they are implemented
by the container. CMR fields are defined in the <relationships> section of the
deployment descriptor. For example, in our Student bean, we have defined
the CMR field courseList
which resembles a Collection of all
courses taken by a student.
We can use the courseList
field in our query to obtain a Collection
of all the teachers that a Student is taking classes from:
SELECT course.teacher
FROM ejbql_student student, IN(student.courseList) course
WHERE student.name=?1
In the FROM
clause, we declare student
to be
an identification variable for the ejbql_student
table. From now
on, we can use "student
" to mean "for each student".
Next, we use the the IN
indentifier to obtain the courseList
for each student. Again we assign an indentification variable,
course
, this time to denote "for each one of the student's
courses".
Now we use the WHERE
clause to make sure we don't leave courses
in the domain that are taken by students other than the one we care about.
Finally, we have collected all the student's courses. We can now return
the name of those teachers whose courses the student is taking. Because
the Course
and Teacher
entities are 1-1 related,
we can simply select a Course's teacher with the '.' operator. We could not do
this in the FROM
clause, with student.courseList
,
because courseList is a Collection.