When the EJB 1.1 was introduced, it took a good beating for its CMP. For one, the specification did not define any standard SQL-like language to interact with the database and to implement persistence. The findByXXX() methods contained application code proprietary to the vendor supplying the CMP tools. This resulted in each application server vendor either defining a proprietary query language, or adopting a query language of its choice. The very reason that the emergence of EJB's WORA (write once, run anywhere) was defeated was that the application components developed using CMP (as defined in the EJB 1.1 specification) became tied down to the application server on which it was developed. To overcome problems of portability associated with CMP, developers resorted to developing entity beans using BMP. The pooling of beans and persistence was then managed by the bean developer. That is when the shortfalls of developing entity beans using BMP-like code came into play. The code was complex and unwieldy and required increased development times. In the EJB 1.1 specification, there was no ideal query language to navigate between a bean class and its dependent classes or any of the member variables of the dependent classes. This resulted in proprietary select or query methods to find information internal to dependent classes. To overcome the cited problems, the EJB 2.0 specification defines a new ANSI SQL92 compliant language, called the EJB Query Language (EJB QL). EJB QL is a simple SQL-based language aimed at only executing queries for in-memory objects in the application server. It is not a full-fledged database SQL language. The application server compiles the EJB QL query that is based on the abstract persistence schema of entity beans and then converts the query into the application server's target language, making it portable. The EJB QL language works with the definitions of entity beans, rather than with the relational database tables themselves. EJB QL can be used by entity beans using either local or remote interfaces as well as dependent objects. The EJB QL language has two types of syntaxes: tag syntax and query syntax. In the following section, you will explore them in more detail. Tag SyntaxThe tag syntax component of the EJB QL language defines how the EJB QL query should be embedded in the ejb-jar.xml deployment descriptor file. The different tags that will be used for embedding the EJB QL query have a well-defined syntax. To enable the EJB QL queries to be used across any EJB 2.0 compliant container, the entries have to be primarily made in the common ejb-jar.xml. Here is how the contents of the ejb-jar.xml file look with the tags: <ejb-jar> <enterprise-beans> <session> ... </session> <entity> ... <abstract-schema-name> </abstract-schema-name> <cmp-field> </cmp-field> <query> <query-method> <method-name> </method-name> <method-params> <method-param> </method-param> </method-params> </query-method> <result-type-mapping> </result-type-mapping> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM objectname AS a WHERE a.cmp-field= ?1]]> </ejb-ql> </query> </entity> </enterprise-beans> </ejb-jar> Take a look at some of the tags in the ejb-jar.xml file in detail:
One thing to keep in mind here is that the value of this tag should be of the object type. For example, if your input parameter is of the type string, then the entry in this parameter would be java.lang.String, and not string alone. However, in case of primitive Java types, just the variable type has to be entered. For example, if your parameter is of the type int, the value corresponding to the <method-param> tag will be int.
Query SyntaxApart from the tag syntax, EJB QL has a well-defined query syntax and grammar like any other SQL language. The basic structure of EJB QL consists of the following three clauses:
Now you will take a look at each of these clauses in detail. The SELECT ClauseThe SELECT clause defines the elements to be extracted from the Cartesian join of the schema names defined in the FROM clause. The return type of the SELECT clause is either a remote interface, a local interface, a persistent field, or a collection of objects implementing the local or remote interface. A code snippet follows: SELECT OBJECT(a) FROM Item AS a WHERE a.itemDesc = ?1 The preceding EJB QL query will return objects of Item where the description field matches the input parameter. Tip To obtain distinct results, you can use either a DISTINCT clause, or specify the return type in the finder method as java.util.Set. The java.util.Set class does not allow duplicate values and it performs an internal DISTINCT sorting, so that it returns the same result set as that obtained by a DISTINCT keyword in the SELECT clause. Additionally, the EJB 2.0 specification defines a list of functions that can be used by developers in the SELECT clause of the EJB QL for strings as well as other primitive data types: CONCAT(String, String) returns a concatenated string. DISTINCT (Object) returns either a distinct object or a set of objects with distinct combinations. SUBSTRING(String, start, length) returns a string. LOCATE(String, String, [startPosition]) returns an int. LENGTH(String) returns an int. ABS(number) returns a converted integer. SQRT(double) returns a double. The FROM ClauseThe FROM clause defines the abstract schema on which the Cartesian join has to be performed to obtain the results requested in the SELECT query and filtered by the WHERE clause. The abstract schema name is used here, and not the database table name. The abstract schema name is the abstract name for an entity bean. A code snippet follows: SELECT OBJECT(a) FROM Item AS a WHERE a.itemDesc = ?1 In the preceding query, Item is the abstract schema name defined in the deployment descriptor file, ejb-jar.xml, under the tag <abstract-schema-name>. Alternatively, this can also be a part of a collection of objects existing in a one-to-many relationship. a is used as a pseudo name and is defined here in the FROM clause after the AS keyword. This pseudo name is used in the SELECT and WHERE clauses too. The WHERE ClauseIn this clause, you get to define the criteria based on which one you wish to perform your select. Almost all comparison operators and Boolean expressions allowed in an SQL language are allowed here. To specify the values to be compared, a number with a question mark sign (?) is used. The number is replaced by that occurrence of the <method-param> ejb-jar.xml tag. The comparison operators which can be used are:
The operators specific to EJB are
Limitations of EJB-QLAs with any language, along with all its advantages come some limitations. Here are some of the limitations of EJB QL:
|