作者:自由的猪 制作整理:左岸网络http://www.leftworld.net |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
第8章 EJB查询语言Dale Green著 Iceshape Zeng译 企业JavaBean查询语言(EJB QL)定义CMP的查找和Select方法的查询动作。EJB QL在SQL92子集的基础上作了一些扩展,以允许在实体Bean抽象模式中定义的关系上定义查询,它的查询范围跨越同一个EJB JAR文件中的关联实体Bean的抽象模式。 EJB QL查询在实体Bean的部署描述符中被定义,通常部署工具会将这些查询转化为底层数据库可执行的目标SQL语句。因此CMP实体Bean有更好的可移植性——它的代码不依赖于特定的底层数据库实现。 本章的例子沿用第6章使用的例子。 本章内容: 术语 简单语法 查询例子 简单查找方法的查询 跨越实体Bean关系查找方法的查询 其它条件查找方法的查询 Select方法的查询 全部语法 BNF范式 EJB QL的BNF文法 FROM子句 Path表达式 WHERE子句 SELECT子句 EJB QL的限制 一.术语下面列了本章用到的术语: ☆ 抽象模式(Abstract schema):实体Bean部署描述符的一部分,定义持久性子段和关系子段 ☆ 抽象模式名(Abstract schema name):EJB QL中引用的逻辑名字,每一个CMP实体Bean指定一个唯一的抽象模式名 ☆ 抽象模式类型(Abstract schema type):所有的EJB QL表达式都归结到一定的类型。如果一个表达式是抽象模式名,缺省地它的类型是定义这个抽象模式名的实体Bean的Local接口。 ☆ BNF范式(Backus-Naur Form):描述高级语言语法的符号。本章的语法都用BNF范式表示。 ☆ 关联查询(Navigation):在EJB QL表达式中跨越关系查询。关联操作符是一个句点 ☆ Path表达式(Path expression):一个可以根据路径找到关系实体Bean的表达式 ☆ 持久性字段(Persistent field):CMP实体Bean中的一个虚拟字段,它存储在数据库中。 ☆ 关系字段(Relationship field):CMP实体Bean中的一个虚拟字段,它标志关系的另一方实体Bean。 二.简单语法本节简要的描述EJB QL的语法一遍你可以进入下一节查询例子。如果想全面了解语法可以转到第三节全部语法。 一个EJB QL查询有三个子句:SELECT、FROM和WHERE。SELECT和FROM子句是必需的,WHERE子句可选。下面是一个符合高级BNF范式语法的EJB QL查询: EJB QL ::= select_clause from_clause [where_clause] SELECT子句定义查询返回的对象或者值,返回类型是一下上种之一:Local接口、Remote接口和持久性字段。 FROM子句声明一个或多个同位变量来定义查询范围,这些变量会在SELECT和WHERE子句中被引用。一个同位变量表示一下元素之一: ☆ 实体Bean的抽象模式名 ☆ 一个一对多关系中“多”方的集合成员 WHERE子句是约束查询返回对象和值的条件表达式。虽然可选但是大部分查询都有一个WHERE子句。 三.查询例子本节用到的例子都来自第6章的RosterApp应用程序的PlayerEJB实体Bean。要查看RosterApp中个企业Bean之间的关系参考图6-1。 简单查找方法的查询 如果你不熟悉EJB QL语言,下面的简单查询将是一个很好的开始: 例1: SELECT OBJECT(p) FROM Player p 查询结果:所有的运动员 对应查找方法:findall() 解释:FROM子句声明一个同位变量p,省略可选关键字AS。上面语句的FROM子句也可以写成: FROM Player AS p 元素Player是PlayerEJB的抽象模式名。因为findall方法在LocalPlayerHome接口中定义,所以这个查询返回LocalPlayer类型的对象。 关于同位变量的更多信息参考下一节。 例2: SELECT DISTINCT OBJECT(p) FROM Player p WHERE p.position = ?1 查询结果:位置等于查找方法传入的位置参数运动员。 查找方法:findByPosition(String position) 解释:在SELECT子句中,OBJECT关键字必须在像p这样的一个单独的同位变量前。 DISTINCT关键字过滤调重复的数据。 WHERE子句检查找到的运动员的位置来约束返回结果。?1表示findByPosition方法的参数。 关于传入参数、DISTINCT关键字和OBJECT关键字的详细信息参考下一节。 例3: SELECT DISTINCT OBJECT(p) FROM Player p WHERE p.position = ?1 AND p.name = ?2 返回结果:在给定位置并且叫给定名字的运动员 查找方法:findByPositionAndName(String position,String name) 解释:position和name都是PlayerEJB的持久性字段。WHERE子句比较这两个字段和findByPositionAndName方法的传入参数。EJB QL用一个问号后跟一个整数来表示方法的传入参数。第一个参数表示为:?1,第二个参数表示成:?2,以此类推。 跨越实体Bean关系查找方法的查询(关联查询) 在EJB QL语言中,一个表达式可以跨越实体Bean关系的另一方进行查询。这些表达式是EJB QL和SQL之间的主要区别,EJB QL跨越关联的实体Bean,而SQL连接多个表。 例4: SELECT DISTINCT OBJECT(p) FROM Player p, IN (p.teams) AS t WHERE t.city = ?1 返回结果:属于在指定城市的组的运动员 查找方法:findByCity(String city) 解释:FROM子句声明了两个同位变量:p和t。p跟Player同义,表示PlayerEJB实体Bean。t表示关系中的另一方TeamEJB。t的声明引用了前面声明的p。IN关键字表明teams是一个TeamEJB的集合。p.teams表达式关联PlayerEJB和TeamEJB,表达式中的句点是关联操作。 在WHERE子句中,city前的句点是一个限定符,不是关联操作符。严格来讲,关联表达式只能使用关系字段,不能使用持久性字段。访问持久性字段时,表达式中的句点作为限定符使用。 关联表达式不可以越过(或更严格的限定)集合类型的关联字段。在表达式的语法中,一个集合值字段是一个终结符。因为teams字段是集合类型,在WHERE子句中不能写成p.teams.city,这是非法的表达式。 详细描述参考下一节的路径表达式。 例5 SELECT DISTINCT OBJECT(p) FROM Player p, IN (p.teams) AS t WHERE t.league = ?1 返回结果:属于特定社团(league)的所有运动员。 查找方法:findByLeague(LocalLeague league) 解释:这个查询跨越了两个关系。p.teams跨越PlayerEJB-TeamEJB关系,t.league跨越TeamEJB-LeagueEJB关系。 在其他例子中,传入参数都是String对象,而这个例子的参数是LocalLeague接口类型,它在WHERE的比较表达式中匹配league关系字段。 例6 SELECT DISTINCT OBJECT(p) FROM Player p, IN (p.teams) AS t WHERE t.league.sport = ?1 返回结果:参加了指定运动项目的运动员 查找方法:findBySport(String sport) 解释:sport是LeagueEJB的持久性字段。要访问sport字段,查询必须先关联PlayerEJB到TeamEJB(p.teams)然后关联TeamEJB到LeagueEJB(t.league)。因为league关系字段不是集合类型,它可以在后面接sport持久性字段。 其它条件查找方法的查询 每一个WHERE子句都必须指定一个条件表达式,这样的条件表达式有很多种。在前面的例子中,条件表达式都是检查相等的比较表达式。下面会给出一些其他类型的条件表达式。关于条件表达式的详尽描述请参考下一节的WHERE子句内容。 例7 SELECT OBJECT(p) FROM Player p WHERE p.teams IS EMPTY 返回结果:不属于任何组的所有运动员 查找方法:findNotOnTeam() 解释:PlayerEJB的关系字段teams是集合类型,如果运动员不属于任何组,则teams集合为空,而条件表达式返回TRUE。参考下一节的空集合比较表达式 例8 SELECT DISTINCT OBJECT(p) FROM Player p WHERE p.salary BETWEEN ?1 AND ?2 返回结果:薪水在指定范围内的运动员 查找方法:findBySalaryRange(double low,double high) 解释:BETWEEN表达式中有三个数学表达式:一个持久性字段(p.salary)和两个传入参数(?1和?2)。可以用下面的表达式替换BETWEEN表达式: p.salary >= ?1 AND p.salary <= ?2 参考下一节的BETWEEN表达式。 例9 SELECT DISTINCT OBJECT(p1) FROM Player p1, Player p2 WHERE p1.salary > p2.salary AND p2.name = ?1 返回结果:返回薪水高于指定名字的运动员的所有运动员 查找方法:findByHigherSalary(String name) 解释:FROM子句声明了Player类型的两个同位变量(p1和p2)。因为WHERE子句需要比较两个运动员(p1和p2)的薪水,所以这里需要两个同为变量。(实际上就是自连接查询)。参考下一节同位变量。 Select方法的查询 下面的例子是Select方法的查询,和查找方法不同,Select方法可以返回持久性字段和其他实体Bean。 例10SELECT DISTINCT t.league FROM Player p, IN (p.teams) AS t WHERE p = ?1 返回结果:指定运动员加入的所有社团 Select方法:ejbSelectLeagues(LocalPlayer player) 解释:该查询的返回类型是LeagueEJB实体Bean的抽象模式,该抽象模式映射到LocalLeagueHome接口。因为t.league不是一个单独的同为变量,所以OBJECT关键字省略。参考下一节SELECT子句。 例11 SELECT DISTINCT t.league.sport FROM Player p, IN (p.teams) AS t WHERE p = ?1 返回结果:指定运动员参与的所有运动项目 Select方法:ejbSelectSports(LocalPlayer player 解释:该查询返回LeagueEJB的持久性字段sport的集合。 四.全部语法本节讨论EJB规范定义的EJB QL语法。下面的大部分资料解释规范,有些还是直接引用规范的内容。 BNF范式 表8-1列出了本章用到的BNF符号
EJB QL语法的BNF定义 下面是这些语法的定义:EJB QL ::= select_clause from_clause [where_clause] from_clause ::= FROM identification_variable_declaration [, identification_variable_declaration]* identification_variable_declaration ::= collection_member_declaration | range_variable_declaration collection_member_declaration ::= IN (collection_valued_path_expression) [AS] identifier range_variable_declaration ::= abstract_schema_name [AS] identifier single_valued_path_expression ::= {single_valued_navigation | identification_variable}.cmp_field | single_valued_navigation single_valued_navigation ::= identification_variable.[single_valued_cmr_field.]* single_valued_cmr_field collection_valued_path_expression ::= identification_variable.[single_valued_cmr_field.]* collection_valued_cmr_field select_clause ::= SELECT [DISTINCT] {single_valued_path_expression | OBJECT(identification_variable)} where_clause ::= WHERE conditional_expression conditional_expression ::= conditional_term | conditional_expression OR conditional_term conditional_term ::= conditional_factor | conditional_term AND conditional_factor conditional_factor ::= [ NOT ] conditional_test conditional_test ::= conditional_primary conditional_primary ::= simple_cond_expression | (conditional_expression) simple_cond_expression ::= comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression between_expression ::= arithmetic_expression [NOT] BETWEEN arithmetic_expression AND arithmetic_expression in_expression ::= single_valued_path_expression [NOT] IN (string_literal [, string_literal]* ) like_expression ::= single_valued_path_expression [NOT] LIKE pattern_value [ESCAPE escape-character] null_comparison_expression ::= single_valued_path_expression IS [NOT] NULL empty_collection_comparison_expression ::= collection_valued_path_expression IS [NOT] EMPTY collection_member_expression ::= {single_valued_navigation | identification_variable | input_parameter} [NOT] MEMBER [OF] collection_valued_path_expression comparison_expression ::= string_value { =|<>} string_expression | boolean_value { =|<>} boolean_expression} | datetime_value { = | <> | > | < } datetime_expression | entity_bean_value { = | <> } entity_bean_expression | arithmetic_value comparison_operator single_value_designator arithmetic_value ::= single_valued_path_expression | functions_returning_numerics single_value_designator ::= scalar_expression comparison_operator ::= = | > | >= | < | <= | <> scalar_expression ::= arithmetic_expression arithmetic_expression ::= arithmetic_term | arithmetic_expression { + | - } arithmetic_term arithmetic_term ::= arithmetic_factor | arithmetic_term { * | / } arithmetic_factor arithmetic_factor ::= { + |- } arithmetic_primary arithmetic_primary ::= single_valued_path_expression | literal | (arithmetic_expression) | input_parameter | functions_returning_numerics string_value ::= single_valued_path_expression | functions_returning_strings string_expression ::= string_primary | input_expression string_primary ::= single_valued_path_expression | literal | (string_expression) | functions_returning_strings datetime_value ::= single_valued_path_expression datetime_expression ::= datetime_value | input_parameter boolean_value ::= single_valued_path_expression boolean_expression ::= single_valued_path_expression | literal | input_parameter entity_bean_value ::= single_valued_navigation | identification_variable entity_bean_expression ::= entity_bean_value | input_parameter functions_returning_strings ::= CONCAT(string_expression, string_expression) | SUBSTRING(string_expression, arithmetic_expression, arithmetic_expression) functions_returning_numerics::= LENGTH(string_expression) | LOCATE(string_expression, string_expression[, arithmetic_expression]) | ABS(arithmetic_expression) | SQRT(arithmetic_expression) FROM子句 FROM子句声明同位变量来定义查询的对象。语法: from_clause ::= FROM identification_variable_declaration [, identification_variable_declaration]*identification_variable_declaration ::= collection_member_declaration | range_variable_declarationcollection_member_declaration ::= IN (collection_valued_path_expression) [AS] identifier range_variable_declaration ::= abstract_schema_name [AS] identifier 标识符 标识符是一个字符序列。头一个字符必须是符合Java变成语言(以下简称Java)的标识符规则的开始字符(字母、$和_),后面的字符要是Java标识符规则的非开始字符(字母、数字、$和_)。(参考J2SE文档中Character类的isJavaIdentifierStart和isJavaIdentifierPart方法的说明。)问号(?)是EJB QL的保留字,不能出现在标识符中。跟Java变量不同的是,EJB QL标识符大小写不敏感。 标识符不能是如下的EJB QL关键字(20个):
这些关键字也是SQL的保留字。以后EJB SQL关键字可能会扩展包含另一些SQL保留字,所以EJB规范建议不要使用其它的SQL保留字作为EJB QL的标识符。 同位变量 同位变量是FROM字句中声明的标识符,尽管SELECT和WHERE子句会引用这些变量,但不能声明它们。所有的同为变量都必须在FROM子句中声明。 因为同位变量也是标识符,所以它有和标识符一样的命名约定和约束。例如,同为变量也是大小写不敏感的也不能使用EJB QL关键字。另外,在给定的EJB JAR文件里,同位变量也不能是其实体Bean的名字和抽象模式名。 FROM子句可以声明多个同位变量,它们之间用逗号隔开。一个声明可以引用前面(左边)声明过的同位变量。如下变量t引用前面声明的p: FROM Player p, IN (p.teams) AS t 同位变量就算不被WHERE子句引用,它的声明仍然可以影响查询结果。比较下面的两个例子: 1.SELECT OBJECT(p) FROM Player p 该查询返回所有的运动员。 2.SELECT OBJECT(p)FROM Player p, IN (p.teams) AS t 因为这里声明了同位变量t,它返回加入了组的运动员 下面的查询返回和上面2相同的结果,但是它的WHERE子句更容易读懂: SELECT OBJECT(p) FROM Player p WHERE p.teams IS NOT EMPTY 同位变量总是表示一个引用,它的类型是声明中使用的表达式的类型。声明可以分为两种:范围变量和集合成员。 范围变量声明 你可以指定一个范围变量以将同位变量声明为一个抽象模式类型。就是说一个同位变量具有实体Bean的抽象模式类型。下面的例子中,同位变量p代表抽象模式Player: FROM Player p 一个范围变量声明可以包含可选的AS操作符: FROM Player AS p 大多是情况下,要获得目标对象,查询可以通过路径表达式跨域实体关系。但是不能通过跨越关系获得的目标对象,你只能用范围变量声明来表示一个查询起点(根)。 例如,查询要比较同一个抽象模式中的多个对象,FROM子句必须为该抽象模式声明多个对应的同位对象(上节例9): FROM Player p1, Player p2 集合成员声明 在一对多关系中,“多”的一方在关系中由实体Bean的集合组成。一个同位变量可以代表集合的成员。为了访问集合成员,变量声明中的路径表达式跨越抽象模式中的实体关系。(路径表达式将在本节后面部分讲到。)因为路径表达式可以嵌套,所以这种关联可以跨越多个关系。(上节例6) 集合成员声明时必须包含IN操作符,但可以省略AS操作符。 下面的例子中,抽象模式名为Player的实体Bean有一个关系字段:teams,同位变量t代表teams集合中的单个成员: FROM Player p, IN (p.te 路径表达式 由于多种原因,使路径表达式成为EJB QL语法中的重要成员。首先它们定义跨越抽象模式中的关系的路径,这些路径定义不仅影响查询范围还同时影响查询结果。其次它们可以出现在EJB QL查询的三种主要子句(SELECT、WHERE和FROM)的任何一种子句中。最后尽管很多EJB QL是SQL的子集,但是路径表达式确实SQL里没有的一种扩展。 语法 路径表达式有两种类型:单值表达式和集合表达式。下面是这两种表达式的语法: single_valued_path_expression ::= {single_valued_navigation | identification_variable}.cmp_field | single_valued_navigation single_valued_navigation ::= identification_variable.[single_valued_cmr_field.]* single_valued_cmr_field collection_valued_path_expression ::= identification_variable.[single_valued_cmr_field.]* collection_valued_cmr_field 在上面的语法定义中,cmp_field表示持久性字段,cmr_field表示关系字段.。single_valued限定关系字段是一对一或者一对多关系单一值的一方。Collection_valued表示关系字段是集合值的一方。 句点(.)在路径表达式中有两种作用。如果句点出现在持久性字段前,那么它表示在字段和同位变量值键的限定符,如果在关系字段前,表示一个关联操作符。 例子 下面的这个查询中,WHERE子句包含一个单值路径表达式。P是一个同位变量,salary是Player的持久性字: SELECT DISTINCT OBJECT(p) FROM Player p WHERE p.salary BETWEEN ?1 AND ?2 接着的这个例子中,WHERE子句也包含一个单值路径表达式,但跨越多个关系。t是一同位变量,league是一个单值关系字段(关系字段中单一值的一方),sport是league的持久性字段: SELECT DISTINCT OBJECT(p) FROM Player p, IN (p.teams) AS t WHERE t.league.sport = ?1 最后的这个例子中,WHERE子句包含一个集合路径表达式。P是同位变量,teams表示集合关系字段: SELECT DISTINCT OBJECT(p) FROM Player p WHERE p.teams IS EMPTY 表达式类型 表达式的类型是表达式结束元素代表的对象的类型。可以使一下任何一种: ☆ 持久性字段 ☆ 单值关系字段 ☆ 集合关系字段 例如,因为salary持久性字段的类型是double,则p.salary表达式的类型也是double。而p.teams表达式的结束元素是teams,它是一个集合关系字段,所以这个表达式的类型是Team的抽象模式类型集合,因为Team是TeamEJB实体Bean的抽象模式名,实际上这个类型映射为实体Bean的Local接口:LocalTeam。关于抽象模式的类型映射参考返回类型部分。 关联查询 路径表达式使查询可以跨越关系中的两个实体Bean。表达式的结束元素决定是否允许这种关联,如果一个表达式包含单值关系字段,那么查询可以继续跨越该字段的关联实体。然而查询不能跨越持久性字段和集合关系值段建立关联。例如p.teams.league.sport是一个非法表达式,因为teams是一个集合关系字段。要获得sport字段,可以在FROM子句中为teams声明一个同为变量t: FROM Player AS p, IN (p.teams) t WHERE t.league.sport = 'soccer' WHERE子句 WHERE子句定义限制查询返回结果的条件表达式。查询返回从数据库中读出的使条件表达式为TRUE的所有值。尽管WHERE子句很常用,但它并不是必需的。如果WHERE子句被省略,查询就返回所有值。下面是WHERE子句的高级语法定义: where_clause ::= WHERE conditional_expression 常量元素 WHERE子句有三种常量:字符串、数字和布尔型。 字符串常量 字符串常量使用单引号括起来的字符序列: 'Duke' 和Java字符串类(String)一样,EJB QL的字符串常量使用Unicode字符编码。 数字常量 WHERE子句支持两种类型的数字常量:精确数字和近似值。 一个精确的数字常量是没有小数点的整数,如65、-233、+12这些。用Java语法描述,精确数字常量支持Java的long类型的表示范围。 一个近似值数字常量是用科学计数法表示的数字,像57.、-85.7、+3.5这样的数字。用Java浮点数描述,近似值数字常量支持double类型的表示范围。 布尔常量 布尔常量只有两个:TRUE和FALSE。大小写不敏感。 传入参数 传入参数用问号(?)后跟一个整数表示。例如第一个参数表示为?1,第二个参数表示为:?2,依次类推。 以下是传入参数的使用规则: ☆ 只能在WHERE子句中使用传入参数 ☆ 在条件表达式中限制只能和单值路径表达式比较 ☆ 必须用从1开始的整数编号而且不能大于对应的查找或者Select方法中的参数个数 ☆ 类型必须和相应查找或者Select方法中的对应参数类型匹配 条件表达式 WHERE子句由条件表达式组成,条件表达式符合一般的比较运算和布尔表达式的运算顺序,同优先级的从左到右运算,用括好可以改变默认的运算顺序。下面是条件表达式的语法定义: conditional_expression ::= conditional_term | conditional_expression OR conditional_term conditional_term ::= conditional_factor | conditional_term AND conditional_factor conditional_factor ::= [ NOT ] conditional_test conditional_test ::= conditional_primary conditional_primary ::= simple_cond_expression | (conditional_expression) simple_cond_expression ::= comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression 运算符和它们的优先级 表8-2按优先级递减的顺序列出了EJB QL的运算符:
BETWEEN表达式 BETWEEN表达式判断一个算术表达式的值是否在某个范围内。语法定义如下: between_expression ::= arithmetic_expression [NOT] BETWEEN arithmetic_expression AND arithmetic_expression 下面的两个表达式等价: p.age BETWEEN 15 AND 19 p.age >= 15 AND p.age <= 19 下面的两个表达式也等价: p.age NOT BETWEEN 15 AND 19 p.age < 15 OR p.age > 19 如果算术表达式有一个空值(NULL),BETWEEN表达式的值不可预料。 IN表达式 IN表达式判断一个字符串是否属于一个字符串常量的集合。语法如下: in_expression ::= single_valued_path_expression [NOT] IN (string_literal [, string_literal]* )其中的单值路径表达式必须是一个字符串类型。如果单值路径表达式的值为(NULL),IN表达式的值不可预料。 在下面的例子中,如果country是UK,IN表达式值是TRUE。如果country是Peru则表达式值为FALSE: o.country IN ('UK', 'US', 'France') LIKE表达式 LIKE表达式判断一个通配符模式和一个字符串是否匹配。语法如下: like_expression ::= single_valued_path_expression [NOT] LIKE pattern_value [ESCAPE escape-character] 其中单值路径表达式是字符串类型,如果为空(NULL),LIKE表达式的值不可预料。Pattern_value是一个可以包含通配符的字符串常量。EJB QL的通配符是下划线(_)和百分号(%)。下划线表示任意单个字符,百分号表示任意字符序列(字符串)。ESCAPE子句指定要从pattern_value的通配符中排除的字符。 表8-3给出了一些LIKE表达式的例子。TRUE和FALSE列表示单值路径表达式的值是列内容时LIKE表达式的值是TRUE或者FALSE。
判断空值(NULL)表达式 此种表达式判断一个单值路径表达式是否是空值。通常用来判断一个单值关系字段是否被赋值。如果单值路径表达式运算是遇到空值则它的值为空。表达式语法: null_comparison_expression ::= single_valued_path_expression IS [NOT] NULL判断集合为空表达式 此种表达式判断集合路径表达式中是否没有元素。就是说它检查一个集合关系字段是否被赋值。语法: empty_collection_comparison_expression ::= collection_valued_path_expression IS [NOT] EMPTY 如果集合路径表达式的值是空,则判断表达式得到一个空值。(If the collection-valued path expression
is 判断集合成员表达式 表达式判断给定值是否是集合的成员。该值和集合成员必须是相同的类型。语法: collection_member_expression ::= {single_valued_navigation | identification_variable | input_parameter} [NOT] MEMBER [OF] collection_valued_path_expression 如果集合路径表达式的值未知,则该判断表达式的值也未知。如果集合路径表达式代表一个空集合,则判断表达式的值为FALSE。 函数表达式 EJB QL提供一些字符串和数学函数,表8-4和8-5列出了这些函数。其中start和length参数都是int类型,它们指示String参数中的位置.number参数可以是int、float和double中的任一类型。
空值(NULL) 如果引用目标不在稳定的存储空间中,则该目标为空。对包含空值的条件表达式,EJB QL采用SQL92定义的语义,简要概括该语义如下: ☆ 如果一个比较操作或者算术操作有一个未知的值,则表达式为空 ☆ 如果一个路径表达式有空值参与运算,则表达式为空 ☆ IS NULL表达式遇到NULL值返回TRUE,IS NOT NULL遇到空值返回FALSE ☆ 布尔运算符和条件表达式的值使用下面的表提供的三种逻辑值(T:TRUE,F:FALSE,U:UNKNOW)
相等 EJB QL中只有同种类型的值可以进行比较。精确和近似数字例外,它们可以比较,在他们比较时,按照Java语言的数学运算进行隐式转换。 EJB QL把这些参加比较的值当作Java对象类型来对待,而不是它们在底层数据库中代表的类型。例如如果一个持久性字段只能是整形或者空值,则它必须被指派给一个Integer对象,而不是一个原始int类型。因为Java对象可以为空而原始类型不能为空,所以这种指派是必需的。 两个字符串只有在它们只包含相同的字符序列时才相等,例如’abc’和’abc ‘就不相等(后者包含一个空个结束)。 同一抽象模式类型的两个实体Bean只有它们的主键值相等时才相等。 SELECT子句 SELECT子句定义查询返回的对象或值的类型。语法: select_clause ::= SELECT [DISTINCT] {single_valued_path_expression |OBJECT(identification_variable)} 返回类型 查询的返回类型必须匹配查询对应的查找或者Select方法的返回类型。 查找方法的查询,返回类型是定义查找方法的实体Bean的抽象模式类型,该抽象模式类型映射到实体Bean的Remote或者Local接口。如果Remote Home接口定义的该查找方法,则返回类型是Remote接口或它的集合);如果是Local Home接口定义的该查找方法,则返回类型是Local接口或它的集合。例如PlayerEJB的LocalPlayerHome接口定义了查找方法findall: public Collection findAll() throws FinderException; findall方法的EJB QL查询返回LocalPlayer接口的集合: SELECT OBJECT(p) FROM Player p Select方法的查询,返回类型可能是以下之一: ☆ Select方法所属实体Bean的抽象模式类型 ☆ 实体关系中另一个实体Bean的抽象模式类型(缺省情况下抽象模式类型映射到实体Bean的Local接口,尽管不常用,你可以在部署描述符中指定映射到Remote接口。) ☆ 持久性字段 例如PlayerEJB实体Bean,包含ejbSelectSport方法,返回一个代表sport的String对象的集合,sport是LeagueEJB的持久性字段。(上节例11) SELECT子句中不能出现集合表达式。如在下面的例子中,SELECT子句中使用p.teams是非法的,因为它是一个集合。而用t(IN(p.teams) AS t)就是合法的,因为它代表teams的单一成员: SELECT t FROM Player p, IN (p.teams) AS t DISTINCT和OBJECT关键字 DISTINCT关键字排除返回值中的重复值。如果查询返回一个java.util.Collection的对象,它允许出现重复值,你可以使用DISTINCT关键字来排除重复值。而当一个方法返回java.util.Set的对象,则DISTINCT关键字就多余了,因为java.util.Set不允许有重复值。 OBJECT关键字必须在单独的同位变量前面,但是不能出现在一个单值路径表达式前。如果同位变量是单值路径表达式的一部分,那么它不是单独的。 五.EJB QL的限制EJB QL由一些局限: ☆ 不支持注释 ☆ Date和Time的值都用Java的long类型表示成毫秒。一个为了产生毫秒值,你也需要使用java.util.Calendar类 ☆ 通常CMP不支持继承,因此不同类型的实体Bean(CMP)无法比较 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||