EJB-QL 用來在CMP類型的EJB中描述 finders和select 方法。設計這種語言的目的是嚴格的描繪內存對象的查詢,而不是數據庫的查詢。 但是EJB-QL的語法與 SQL非常相似。 他有三個基本語句: SELECT, FROM, WHERE.。通過這幾個語句可以實現各種各樣的組合。本文的目的不是解釋 EJB-QL的各種用法。我們會給出幾種語法,并用幾個例子來描述它。
<ejb-ql> 標記
EJB-QL不能單獨使用,必須定義在ejb-jar.xml文件中的 <ejb-ql> 標記中。這個標記屬于 <query> 標記,<query>定義EJB中的查詢(finder或者 select方法)。EJB容器可以將查詢轉化為 finder或者 select方法的具體實現。. 下面是一個<ejb-ql> 標記的例子。.
<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>hotelEJB</ejb-name>
...
<abstract-schema-name>hotelSchemaName</abstract-schema-name>
<cmp-field>...
...
<query>
<query-method>
<method-name>findByCity</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(h) FROM hotelSchemaName AS h WHERE h.city = ?1]]>
</ejb-ql>
</query>
</entity>
...
</enterprise-beans>
...
</ejb-jar>
藍色的為EJB-QL 查詢,紅色的為 <![CDATA[...]]> 為特定的 XML符號,注意必須一直用這種表示方法。
常用語法
SELECT OBJECT(variable)
FROM abstractSchemaName [AS] variable
[WHERE value comparison value]
上面是最常用的語法,后面我們會看到更多的語法要素。在這個語法中,可以在FROM 中聲明一個或者多個 變量(variables), 在SELECT 和 WHERE 中引用。 注意 abstractSchemaName,,它與 ejb-jar.xml中 entity 標記中聲明的一致。
value 可以是一個參數( parameter), 數字(numeric或者字符( string),變量( variable), 變量中的成員( member inside this variable),或者常量(例如 'Pleasant Inn', 23, TRUE).。每個查詢有一個返回類型( return type)。 Values and return types can be of 6 different data types.
SELECT OBJECT(h)
FROM hotelSchemaName AS h 返回所有的 hotels.
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.city = 'San Diego' 返回在 San Diego的 hotels .
在 SELECT語句中,關鍵字DISTINCT 可以避免查詢出現重復的值。事實上,對于finder方法,由于其返回實體Bean,而實體Bean本身不會重復(因為其主關鍵字不同)。 但是對于 select 方法,可能就會有重復。
Select 方法的語法
當處理一個select方法時,返回類型 ( SELECT語句) 可以不用是 OBJECT(x)。 可以為任意類型的任意值。示例如下:
SELECT [DISTINCT] value
FROM abstractSchemaName [AS] variable
[WHERE ...]
保留關鍵字
EJB-QL保留關鍵字如下:
SELECT
FROM
WHERE OBJECT
AS
IN NOT
AND
OR
LIKE
ESCAPE
BETWEEN
IS
NULL
EMPTY
MEMBER
OF TRUE
FALSE LENGTH
LOCATE
CONCAT
SUBSTRING
ABS
SQRT
返回類型
所有的查詢必須返回下面中的一種:
與 SELECT 語句中定義的對象一致的類型(type)
一個包含這種類型的Collection (當不使用SELECT DISTINCT時允許重復)
一個包含這種類型的 Set (不允許重復,必須用 SELECT DISTINCT)
選擇什么取決于你,下面是相應的一些示例:
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.id = ?1 finder 方法如下:
abstract public Hotel findByHotelID(String hotelID);
(其實這個例子沒有必要,因為findByPrimaryKey 完成的是同樣的功能)
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.city = ?1 (允許重復)
or
SELECT DISTINCT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.city = ?1 (不重復) finder 方法如下:
abstract public Collection findByCity(String city);
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.capacity >= ?1 finder 方法如下:
abstract public Set findByCapacity(integer numberOfPeople);
變量
變量在 FROM中聲明,表示一個 EJB對象。可以在 SELECT 和 WHERE 語句中聲明。變量的類型在 ejb-jar.xml中的 abstract schema name 中聲明。
后邊我們會討論 range variables
成員操作
通過點(".")你可以說明一個成員屬于一個對象,通過點(".")你可以說明任意的cmp-field 名字,或者是一個單值的 cmr-field 的名字。你可以通過(".")操作單值對象(包括數據成員和關系鏈)。下面是一些示例:
SELECT OBJECT(h)
FROM hotelSchemaName h
WHERE ... ... h.capacity > 100
... h.owner = ?1
... h.owner.name = 'Harry'
... h.owner.hotel = h
... h.rooms = ?1 (這里的 cmp-field 名為 'city')
(這里的 cmr-field 'owner' 包含一個唯一的Owner對象)
(這里的owner包含一個 cmp-field 'name')
(這里owner 包含 cmr-field 'hotel'; 這個條件總為真)
(語法錯誤 – 不能使用一個 Collection cmr-field – 應該使用 range變量語法替代 )
Range Variable Syntax
當一個變量的成員是一個 Collection時,你不能通過點(".")操作它。你必須指定一個新的變量 ,這個變量回迭代(iterate)Collection中的每一個記錄。下面是語法
SELECT [DISTINCT] OBJECT(variable)
FROM abstractSchemaName [AS] variable, IN (variable.collectionMember) [AS] variable2
[WHERE ...]
(注意這里的IN操作與WHERE中的不同),你可以在WHERE中 使用新定義的變量 ,就像一般的變量一樣。
SELECT DISTINCT OBJECT(h)
FROM hotelSchemaName AS h, IN (h.rooms) AS r
WHERE r.smoking = TRUE
(返回所有不吸煙的房間)
WebLogic Server 6.1 : range變量語法 在WLS是不同的。下面是一個例子 :
SELECT DISTINCT OBJECT(h)
FROM hotelSchemaName AS h, r IN h.rooms
WHERE r.smoking = TRUE
參數
當finder或者select方法有一個或者多個參數時,可以用"?n"來表示第n個參數,下面是一個 finder方法的例子:
abstract public Hotel findByCityAndState(String city, String state);
你可以用?1表示參數city, ?2表示state,EJB-QL如下所示:
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.city = ?1 AND h.state = ?2
條件操作符
條件操作符是很多的,可以通過括號( )來區分優先級,,通過 AND或者OR合并,例如下面的例子:
... WHERE (h.owner.name = 'Harry' AND h.capacity > 100) OR (h.owner.name = 'Joe' AND h.capacity > 200)
下面是這些操作符的詳細列表
NOT
顛倒當前的條件
... WHERE NOT (h.capacity > 100)
等價于:
... WHERE (h.capacity <= 100)
[NOT] LIKE
對字符串進行模式匹配,模式可以包含統配符: % 表示任意字符串, _ 表示單個字符串。統配符可以通過使用 ESCAPE后面跟一個換碼符置換掉。
... WHERE h.state LIKE 'K%'
(將返回在 Kentucky 或者 Kansas的hotel)
... WHERE h.owner.name LIKE 'J__'
(兩個下劃線 '_')
(將返回 Joe擁有的hotel)
... WHERE h.id LIKE 'A_1%' ESCAPE ''
(將返回以 "A_1"開頭的hotel。這里下劃線 "_" 被反斜杠 ""置換掉)
[NOT] BETWEEN x AND y
檢查是否在兩個數值的范圍中
... WHERE h.capacity BETWEEN 100 AND 200
IS [NOT] NULL
檢查對象是否為 'null'.
... WHERE h.owner IS NULL
(返回owner為空的hotel)
[NOT] IN listOfStrings
在 WHERE中,檢查一個字符串是否在一系列的字符串之中。 這與 FROM中的IN操作不同。
... WHERE h.state IN ('Ohio', 'Texas', ?1)
[NOT] MEMBER [OF]
檢查一個值是否在一個集合中
... WHERE ?1 MEMBER OF h.rooms
(返回包含某一個的房間的 hotel )
=, <>
檢查是否相等
... WHERE h.owner.name = 'Harry'
... WHERE h.owner.name <> 'Joe'
<, >, <=, >=
數字間的比較,對數字和日期有效
... WHERE h.capacity >= 100
IS [NOT] EMPTY
檢查一個集合Collection中是否有元素
... WHERE h.rooms IS EMPTY
(返回沒有房間的 hotels)
數據類型
EJB-QL中共有6中數據類型,它們可以用于返回值,參數,常量,變量。
Objects
它是一個一般的 Java object.。這樣的一個object可以直接被映射為一個abstract schema name,,或者其它 object的成員
SELECT OBJECT(h)
FROM hotelSchemaName h
WHERE h.owner = ?1
(這里的object 為 h, h.owner 和 ?1)
Collections
可以表示為 range變量, 一個object的成員, 或者使用select方法時,返回值為 Collection
SELECT OBJECT(h)
FROM hotelSchemaName h
WHERE ?1 MEMBER OF h.rooms
(Collection 為 h.rooms)
SELECT OBJECT(h)
FROM hotelSchemaName h, IN h.rooms AS r
WHERE r = ?1
( Collections 為 r 和 h.rooms)
SELECT h
FROM hotelSchemaName
(返回所有hotel的Collection )
Strings
可以用作字符 參數,成員變量 ,或者單引號 '中定義的常量。
... WHERE h.owner.name = 'Harry'
(String為 h.owner.name (變量) 和 'Harry' (常量))
... WHERE h.owner.name = 'O''Sullivan'
(常量)
Numbers
可以用作數字參數,成員變量 ,常量。 number 可以為負數 (加 -) 或者小數 (加.),甚至是科學計數法。 integer 轉換為 float是自動完成的 。
13
-16
17.2
1.98E4
45 + 12.1 (自動轉換為 float)
Dates
日期其實是另一種形式的數字。如果用常量來表示, 就是從 01/01/1970 00:00:00 GMT后以秒為單位的一個數字。如果是 參數或者成員變量, 必須是一個 Date對象。
... WHERE reservation.arrivalDate = ?1
(這里的 date是成員變量 arrivalDate 和參數)
... WHERE reservation.arrivalDate < ??????? (這里的值需要計算)
Booleans
布爾型參數 或者成員變量,或者常量TRUE 或者 FALSE
... WHERE room.smoking = TRUE
字符串函數
LENGTH(s)
返回字符串的長度
... WHERE LENGTH(h.owner.name) > 3
LOCATE(s, substr [, startPosition])
返回以各子串在字符串中的位置。 當指定起始點后,子串的搜索從起始點開始。
... WHERE LOCATE(h.owner.name, 'rr') = 2
(Harry's hotel 會被返回)
... WHERE LOCATE(h.owner.name, 'rr', 3) >= 0
(從位置 3開始, Harry's hotel 將不會被返回)
CONCAT(s1, s2)
連接兩個字符串為新的字符串
SELECT CONCAT (CONCAT( h.owner.name, ', the owner of '), h.name)
FROM hotelSchemaName AS h
(select方法返回所有的hotel的所有owner,返回值為一個字符類型的集合)
SUBSTRING(s, startPosition, length)
根據指定位置,指定的字符串數從字符串中得到一個字串。
... WHERE SUBSTRING(h.owner.name, 0, 2) = 'Jo'
(將會返回Joseph, Joe, 等, 等價于h.owner.name LIKE 'Jo%')
數字函數和操作
ABS(n)
返回一個數字的絕對值
SELECT ABS(a.balance)
FROM accountSchemaName AS a
WHERE a.balance < 0
(select方法將會返回所有的資產為負的記錄,但返回值為正的)
SQRT(n)
返回數字的平方根
SELECT OBJECT(a)
FROM accountSchemaName AS a
WHERE SQRT(a.balance) = 2
(返回資產為4的賬號)
+, -, *, /
加,減,乘,除操作
SELECT ABS(a.balance) FROM accountSchemaName AS a
WHERE a.balance + 1 = 5
(返回資產為4的賬號)
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.capacity / 2 >= ?1
SELECT OBJECT(h)
FROM hotelSchemaName AS h
WHERE h.capacity >= ?1 * 2
(上面的兩個查詢都是返回指定容量雙倍的hotel)
SELECT h.capacity - 10
FROM hotelSchemaName AS h
(返回 hotel的容量 ,返回值會減去10)