[读书笔记]EJB QL学习小结

语法和范例
EJB规范正式使用Bacchus Normal Form(BNF)定义EJB QL查询的语法。本节的学习有一定的难度,但对于EJB QL语法的介绍是比较详尽的。本节在介绍EJB QL语法是,使用了注释和范例。
一个EJB QL查询可采用如下的方式定义:
EJB QL ::= select_clause from_clause [where_clause]
这表明EJB QL查询中包括一个select_clause和一个from_clause,还可以包括一个where_clause。现在你就能看到EJB QL和ANSI SQL之间存在相似之处。
ANSI SQL中,SELECT子句中的列与FROM子句中的数据表示相关联的。因此在学习EJB QL时,先学习from_clause在学习select_clause是有道理的;毕竟,对于一个正确的EJB QL查询语句而言,两者都是不可或缺的。
from_clause
from_clause定义如下:
from_clause::=FROM identification_variable_declaration
[, identification_variable_declaration]*
这表明在EJB QL查询中,from_clause包括一个或多个identification_variable_declaration子句。这一点与ANSI SQL下SQL语句的FROM子句列出一个或多个数据表/视图相似。Identification_variable_declaration子句定义如下:
identification_variable_declaration子句定义:
{range_variable_declaration | collection_member_declaration}
[AS ] identification_variable

where

range_variable_declaration ::= abstract_schema_name

and

collection_member_declaration ::= IN (collection_valued_path_expression)
collection_valued_path_expression ::=
identification_variable.
[single_valued_cmr_field.]*
collection_valued_cmr_field

也就是说,from_clause中的每一项或者是一个abstract_schema_name,或者是IN(o.abc.def.xyz)这种形式的表达式。abstract_schema_name可能是一种比较容易理解的表达式,每个CMP实体bean都对应一个最终在部署描述符中声明的abstract_schema_name。因此,这与ANSI SQL中列出对应bean的数据表十分相似。
IN(o.abc.def.xyz)表达式与OCL表达式相似。"o"指的是前面AS表达式分配的identification_variable。换句话说,它也对应于from_clause中的某些abstract_schema_name(即bean)。"abc","def"均为single_value_cmr_field。也就是说,o bean中有字段返回单个的元素。abc是o的一个字段,返回到bean的引用,而def是此引用的一个字段,含有一个xyz字段。xyz字段返回某些其它数据(bean或其他)的Collection或List。
感觉有点乱套了吧?学习事例中的某些例子可以帮你清理一下纷乱的头绪。假设Job bean有一个称为Job的抽象模式名,而Customer bean有一个叫Customer的抽象模式名。

FROM Job AS j

设置一个叫j的identification_variable,指的是Job模式。这里与ANSI SQL的比较很明显;两者的语法是一样的。


FROM Job AS j, IN(j.skills) AS s
和上文一样设置一个叫j的identification_variable,同时还设置了一个名为s的identification_variable, s变量值的是与Job bean的关联的每一项技能。
与上述EJB QL语言对应的ANSI SQL语句如下:
FROM Job AS j
INNER JOIN JobSkill AS s
On s.customer = j.customer
AND s.ref = j.ref

或者如果你喜欢老式的ANSI SQL语句,则为:
FROM Job AS j, JobSkill AS s
WHERE s.customer=j.customer
AND s.ref=j.ref

下面是另外一个例子:
FROM Job AS j, IN(j.location.jobs) AS k
如上文一样设置j identification_variable, 同时设置一个名为k的identification_variable变量,k指的是所有与原始职位具有相同地理位置信息的职位。注意j.location返回一个到职位Location bean的引用,然后j.location.jobs返回Location的Jobs Collection。当然,此Collection不但包括原始职位,而且包括其他职位。
与上述EJB QL语句相对应的ANSI SQL语句如下,可以看出这是一个自我联合语句:
FROM Job AS j
INNER JOIN Job AS k
ON j.location = k.location

or in the old money:

FROM Job AS j, Job AS k
WHERE j.location = k.location

select_clause
select_clause的定义如下:
select_clause ::= SELECT [DISTINCT] {single_valued_path_expression |
OBJECT (identification_variable)}

select_clause中比较容易的是SELECT OBJECT(O)类型的语句,这里o是from_clause定义的一个identification_variable变量(现在你知道为什么要先讲述from_clause了)。SELECT OBJECT(o)语句从数据存储集中返回示例bean所需的所有数据。在ANSI SQL领域,此语句类似于SELECT * FROM... ...
所有的查找方法都必须使用SELECT OBJECT(o)类型的语句,此时返回的是与bean(查找方法是为此bean指定的)关联的模式的对象.
  另外一种是使用single_valued_path_expression的选择子句,这种子句之供选择方法使用,前文中我们曾简单地介绍过(下文有更多地介绍)。
  下面是学习实例中的一些例子。
  SELECT OBJECT(j)
FROM Job AS j
将返回所有的职位。如果JobLocalHome接口定义了叫findAll()的查找方法,那么上述语句就是对应的EJB QL查询语句.
  
下一个例子
  SELECT DISTINCT OBJECT(s)
FROM Job AS j, IN(j.skills) AS s
可返回职位使用的所有技能.由于某些技能是多个职位所需要的,因此使用DISTINCT关键字删除这些重复的技能.此查询语句可能与SkillHome接口中名为findAllRequiredSkills()的查找方法有关。
  其他类型的查询子句使用single_valued_path_expression。其定义如下:
  single_valued_path_expression ::= {single_valued_navigation | identification_variable}
.cmp_field | single_valued_navigation

此定义中single_valued_navigation为:
  single_valued_navigation ::= identification_variable.{single_valued_cmr_filed.}*
single_valued_cmr_field
将上述定义综合在一起,single_valued_path_expression只不过是一串(一个也没有或多个)single_valued_cmr_fields(将引用返回到单个的bean而不是返回到集合的cmr字段),最后以cmp字段结束。
  在下面的例子中
  SELECT DISTINCT j.location.name
FROM Job AS j

location 是Job模式的cmr字段(用j来标识),而name是被cmr字段引用的bean(显然是一个Location bean)的cmp字段。
  此语句返回所有职位信息的地理位置名称。将此语句与ANSI SQL语句进行比较,你会发现EJB QL语句实际上更简单些(因为它使用OCL风格的路径表达式在bean之间进行导航):
  SELECT DISTINCT l.name
FROM Job AS j INNER JOIN Location AS l ON j.location = l.location

然而,下面的语句是不合法的:
  SELECT DISTINCT j.skills.name
FROM Job AS j

这是因为Job 的skills cmr字段返回的是一个技能集合,而不是单独一项技能。这种查询的正确表达方式如下:
  SELECT DISTINCT s.name
FROM Job AS j, IN(j.skills) AS s

  你可以将s标识变量看作skills cmr字段返回的技能集合的示例符。
  注意EJB QL中select_clause中只能返回单项信息,因此下述语句也是不合法的:
  SELECT DISTINCT j.location, j.location.description
FROM Job AS j

where_clause
EJB QL中where_clause是可选的,但大多数情况下都要使用where_clause。BNF中where_clause如下:
  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

这只能说明where_clause可通过常见的AND、OR和NOT来联合。使用BNF定义的where_clause中,一些相当简单的概念被定义的有些含混晦涩,因此在下文中解释一下:
  条件测试使用=、、>=、等操作符。这些操作符可应用到数字和日期时间(全部操作符)、字符串、布尔值和实体bean(使用=和操作符)。前面课程中说过,如果实体bean的主键相同,那么这些实体被认为是相同的。
  比较时可能使用输入参数,这些参数对应于查找或选择方法中的参数。稍后详细讲述这部分内容。
  与ANSI SQL一样,算术表达式使用BETWEEN ... AND操作符.
  字符串的比较可使用IN或LIKE操作符,这一点和ANSI SQL是一样的.与Java不同,where_clause中字符串使用单引号.
  使用IS NOT NULL操作符判断对象是否为null.同样,此语法也是从ANSI SQL借用来的。
  注意:ANSI SQL支持可设为null的原始值这一概念(int等等),不过java和EJB QL不支持。然而,使用包装类作为cmp字段或在EJB QL表达式中使用包装类可模拟null原始值。
  在EJB QL中还使用其他很多操作符和内建函数,但首先我们一次看一下使用上述操作符的例子。
  SELECT OBJECT(c)
FROM Customer AS c
WHERE c.name LIKE "J%"
此语句会查找出名字的第一个字母是J的所有客户。注意这里使用了ANSI SQL中的通配符(%匹配零个或多个任意字符,_只匹配一个字符)。
  下面的语句
  SELECT OBJECT(j)
FROM Jobs AS j
WHERE j.location IS NULL

会查找到地理位置没有指定的全部职位。
  SELECT l.description
FROM Location AS l
WHERE l.name IN("London"、"Washington")
返回地理位置是伦敦和华盛顿的记录的描述。
  where_clause还可以包含一些输入参数,这些参数对应于本地Home接口或bean定义的查询方法/选择方法的参数。
  例如,Job bean在JobLocationHome接口中声明了下面的查找方法:
  Collection findByCustomer(String customer);
  此次查找方法的EJB QL查询如下:
  SELECT OBJECT(j)
FROM Job AS j
WHERE j.customer = ?1

?1作为一个占位符,而1表示查找方法的第一个参数(customer字符串)与此输入参数隐含绑定。与JDBC SQL字符串不同,之所以需要这个数字是因为绑定是隐含的而不是明显的。在查询中若一个单独参数被使用多次,那么也需要这样一个数字。例如,我们来看下面的查找方法:
  Collection findLocaitonNamedOrNamedShorterThan(String name);
这个方法有一个EJB QL查询语句:
  SELECT OBJECT(l)
FROM Location AS l
WHERE l.name=?1
OR LENGTH(l.name)
此语句使用内建函数LENGTH返回一个String的长度。在任何情况下这个另类的查找方法都可找到那些有具体名字的地理位置,并将所有小雨提供名字长度的名字返回。我们看到?1展位副出现了不止一次,这是因为需要在两个地方将名字参数绑定到查询。
  EJB QL只定义了少数几个内建函数.在这些内建函数中,返回字符串的函数是CONTACT和SUBSTRING;返回数据的函数是LENGTH、ABS、SORT和LOCATE。LOCATE函数与String.indexOf(String str, int fromIndex)函数具有相同的功能。
EJB QL只定义了两个终结操作符——IS [NOT] EMPTY和[NOT] MEMBER OF。ANSI SQL中不存在着两个操作符等价物,但在OCL中却存在。
IS [NOT] EMPTY 操作符类似于OCL中的isEmpty操作符,可用来判断cmr字段返回的集合是否为空。例如,以下语句:
SELECT OBJECT(s)
FROM Skill AS s
WHERE s.jobs IS EMPTY

将没有任何职位需要的技能全部返回。这可以是SkillLocalHome接口的查询方法的查询,方法名字类似于findNotNeededSkills()。
实际上,这种查询也可用ANSI SQL语句描述,但需要一个字查询:
SELECT s.*
FROM Skill AS s
WHERE NOT EXISTS
(SELECT *
FROM JobSkill AS j
WHERE s.skill = j.skill)
[NOT]MEMBER OF操作符类似于OCL的include操作符。考虑一下下面JobLocalHome接口中的查询方法:
Collection findJobsRequiringSkill(SkillLocal skill) ;

相关的EJB QL查询如下:
SELECT OBJECT(j)
FROM Job AS j
WHERE ?1 MEMBER OF j.skills

同样,这条语句也可在ANSI SQL中实现,同样需要使用一个子查询:
SELECT j.*
FROM Job AS j
WHERE EXISTS
(SELECT *
FROM JobSkill AS s
WHERE j.customer = s.customer
AND j.ref = s.ref
AND s.skill = ?1)

更多内容
你可能听说过“OO/关系型阻抗错配”,即要处理对象必须示例每个对象,然后向此对象发送一条消息。另一方面,关系型理论共享某些公共属性的元素集合;要想有效地表示这些元素而不对其进行示例,则需要打破封装。
EJB QL为解决这些问题作了大量的工作。通过允许在面向集合的语法中表达查询,EJB容器在数据存储集为RDBMS时可轻松地将这些查询映射到ANSI SQL。另一方面,查找方面生成的实现仅返回对象或对象的集合。
然而,EJB QL确实有一些限制。例如,当构造EJB QL查询时,仅仅可使用bean之间声明的关联。将任意字段联合在一起(如ANSI SQL那样)是不可能的事情。例如,某些Customer(客户)同时还是Applicant(求职者),那么将无法使用诸如Applicant.name=Customer.name之类的条件来表示这些Customer。
大量的实例证明EJB QL没有(尚不如)ANSI SQL功能强大。例如,EJB QL不支持分组和汇总、排序、子查询和联合。随着EJB QL的不断成熟,这些功能会不断添加进来。尽管EJB QL不支持子查询,但由于IS[NOT] EMPTY和[NOT] MEMBER OF操作符的存在,我们不使用自查询也能实现相同的功能。
语法和范例
EJB规范正式使用Bacchus Normal Form(BNF)定义EJB QL查询的语法。本节的学习有一定的难度,但对于EJB QL语法的介绍是比较详尽的。本节在介绍EJB QL语法是,使用了注释和范例。
一个EJB QL查询可采用如下的方式定义:
EJB QL ::= select_clause from_clause [where_clause]
这表明EJB QL查询中包括一个select_clause和一个from_clause,还可以包括一个where_clause。现在你就能看到EJB QL和ANSI SQL之间存在相似之处。
ANSI SQL中,SELECT子句中的列与FROM子句中的数据表示相关联的。因此在学习EJB QL时,先学习from_clause在学习select_clause是有道理的;毕竟,对于一个正确的EJB QL查询语句而言,两者都是不可或缺的。
from_clause
from_clause定义如下:
from_clause::=FROM identification_variable_declaration
[, identification_variable_declaration]*
这表明在EJB QL查询中,from_clause包括一个或多个identification_variable_declaration子句。这一点与ANSI SQL下SQL语句的FROM子句列出一个或多个数据表/视图相似。Identification_variable_declaration子句定义如下:
identification_variable_declaration子句定义:
{range_variable_declaration | collection_member_declaration}
[AS ] identification_variable

where

range_variable_declaration ::= abstract_schema_name

and

collection_member_declaration ::= IN (collection_valued_path_expression)
collection_valued_path_expression ::=
identification_variable.
[single_valued_cmr_field.]*
collection_valued_cmr_field

也就是说,from_clause中的每一项或者是一个abstract_schema_name,或者是IN(o.abc.def.xyz)这种形式的表达式。abstract_schema_name可能是一种比较容易理解的表达式,每个CMP实体bean都对应一个最终在部署描述符中声明的abstract_schema_name。因此,这与ANSI SQL中列出对应bean的数据表十分相似。
IN(o.abc.def.xyz)表达式与OCL表达式相似。"o"指的是前面AS表达式分配的identification_variable。换句话说,它也对应于from_clause中的某些abstract_schema_name(即bean)。"abc","def"均为single_value_cmr_field。也就是说,o bean中有字段返回单个的元素。abc是o的一个字段,返回到bean的引用,而def是此引用的一个字段,含有一个xyz字段。xyz字段返回某些其它数据(bean或其他)的Collection或List。
感觉有点乱套了吧?学习事例中的某些例子可以帮你清理一下纷乱的头绪。假设Job bean有一个称为Job的抽象模式名,而Customer bean有一个叫Customer的抽象模式名。

FROM Job AS j

设置一个叫j的identification_variable,指的是Job模式。这里与ANSI SQL的比较很明显;两者的语法是一样的。


FROM Job AS j, IN(j.skills) AS s
和上文一样设置一个叫j的identification_variable,同时还设置了一个名为s的identification_variable, s变量值的是与Job bean的关联的每一项技能。
与上述EJB QL语言对应的ANSI SQL语句如下:
FROM Job AS j
INNER JOIN JobSkill AS s
On s.customer = j.customer
AND s.ref = j.ref

或者如果你喜欢老式的ANSI SQL语句,则为:
FROM Job AS j, JobSkill AS s
WHERE s.customer=j.customer
AND s.ref=j.ref

下面是另外一个例子:
FROM Job AS j, IN(j.location.jobs) AS k
如上文一样设置j identification_variable, 同时设置一个名为k的identification_variable变量,k指的是所有与原始职位具有相同地理位置信息的职位。注意j.location返回一个到职位Location bean的引用,然后j.location.jobs返回Location的Jobs Collection。当然,此Collection不但包括原始职位,而且包括其他职位。
与上述EJB QL语句相对应的ANSI SQL语句如下,可以看出这是一个自我联合语句:
FROM Job AS j
INNER JOIN Job AS k
ON j.location = k.location

or in the old money:

FROM Job AS j, Job AS k
WHERE j.location = k.location

select_clause
select_clause的定义如下:
select_clause ::= SELECT [DISTINCT] {single_valued_path_expression |
OBJECT (identification_variable)}

select_clause中比较容易的是SELECT OBJECT(O)类型的语句,这里o是from_clause定义的一个identification_variable变量(现在你知道为什么要先讲述from_clause了)。SELECT OBJECT(o)语句从数据存储集中返回示例bean所需的所有数据。在ANSI SQL领域,此语句类似于SELECT * FROM... ...
所有的查找方法都必须使用SELECT OBJECT(o)类型的语句,此时返回的是与bean(查找方法是为此bean指定的)关联的模式的对象.
  另外一种是使用single_valued_path_expression的选择子句,这种子句之供选择方法使用,前文中我们曾简单地介绍过(下文有更多地介绍)。
  下面是学习实例中的一些例子。
  SELECT OBJECT(j)
FROM Job AS j
将返回所有的职位。如果JobLocalHome接口定义了叫findAll()的查找方法,那么上述语句就是对应的EJB QL查询语句.
  
下一个例子
  SELECT DISTINCT OBJECT(s)
FROM Job AS j, IN(j.skills) AS s
可返回职位使用的所有技能.由于某些技能是多个职位所需要的,因此使用DISTINCT关键字删除这些重复的技能.此查询语句可能与SkillHome接口中名为findAllRequiredSkills()的查找方法有关。
  其他类型的查询子句使用single_valued_path_expression。其定义如下:
  single_valued_path_expression ::= {single_valued_navigation | identification_variable}
.cmp_field | single_valued_navigation

此定义中single_valued_navigation为:
  single_valued_navigation ::= identification_variable.{single_valued_cmr_filed.}*
single_valued_cmr_field
将上述定义综合在一起,single_valued_path_expression只不过是一串(一个也没有或多个)single_valued_cmr_fields(将引用返回到单个的bean而不是返回到集合的cmr字段),最后以cmp字段结束。
  在下面的例子中
  SELECT DISTINCT j.location.name
FROM Job AS j

location 是Job模式的cmr字段(用j来标识),而name是被cmr字段引用的bean(显然是一个Location bean)的cmp字段。
  此语句返回所有职位信息的地理位置名称。将此语句与ANSI SQL语句进行比较,你会发现EJB QL语句实际上更简单些(因为它使用OCL风格的路径表达式在bean之间进行导航):
  SELECT DISTINCT l.name
FROM Job AS j INNER JOIN Location AS l ON j.location = l.location

然而,下面的语句是不合法的:
  SELECT DISTINCT j.skills.name
FROM Job AS j

这是因为Job 的skills cmr字段返回的是一个技能集合,而不是单独一项技能。这种查询的正确表达方式如下:
  SELECT DISTINCT s.name
FROM Job AS j, IN(j.skills) AS s

  你可以将s标识变量看作skills cmr字段返回的技能集合的示例符。
  注意EJB QL中select_clause中只能返回单项信息,因此下述语句也是不合法的:
  SELECT DISTINCT j.location, j.location.description
FROM Job AS j

where_clause
EJB QL中where_clause是可选的,但大多数情况下都要使用where_clause。BNF中where_clause如下:
  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

这只能说明where_clause可通过常见的AND、OR和NOT来联合。使用BNF定义的where_clause中,一些相当简单的概念被定义的有些含混晦涩,因此在下文中解释一下:
  条件测试使用=、、>=、等操作符。这些操作符可应用到数字和日期时间(全部操作符)、字符串、布尔值和实体bean(使用=和操作符)。前面课程中说过,如果实体bean的主键相同,那么这些实体被认为是相同的。
  比较时可能使用输入参数,这些参数对应于查找或选择方法中的参数。稍后详细讲述这部分内容。
  与ANSI SQL一样,算术表达式使用BETWEEN ... AND操作符.
  字符串的比较可使用IN或LIKE操作符,这一点和ANSI SQL是一样的.与Java不同,where_clause中字符串使用单引号.
  使用IS NOT NULL操作符判断对象是否为null.同样,此语法也是从ANSI SQL借用来的。
  注意:ANSI SQL支持可设为null的原始值这一概念(int等等),不过java和EJB QL不支持。然而,使用包装类作为cmp字段或在EJB QL表达式中使用包装类可模拟null原始值。
  在EJB QL中还使用其他很多操作符和内建函数,但首先我们一次看一下使用上述操作符的例子。
  SELECT OBJECT(c)
FROM Customer AS c
WHERE c.name LIKE "J%"
此语句会查找出名字的第一个字母是J的所有客户。注意这里使用了ANSI SQL中的通配符(%匹配零个或多个任意字符,_只匹配一个字符)。
  下面的语句
  SELECT OBJECT(j)
FROM Jobs AS j
WHERE j.location IS NULL

会查找到地理位置没有指定的全部职位。
  SELECT l.description
FROM Location AS l
WHERE l.name IN("London"、"Washington")
返回地理位置是伦敦和华盛顿的记录的描述。
  where_clause还可以包含一些输入参数,这些参数对应于本地Home接口或bean定义的查询方法/选择方法的参数。
  例如,Job bean在JobLocationHome接口中声明了下面的查找方法:
  Collection findByCustomer(String customer);
  此次查找方法的EJB QL查询如下:
  SELECT OBJECT(j)
FROM Job AS j
WHERE j.customer = ?1

?1作为一个占位符,而1表示查找方法的第一个参数(customer字符串)与此输入参数隐含绑定。与JDBC SQL字符串不同,之所以需要这个数字是因为绑定是隐含的而不是明显的。在查询中若一个单独参数被使用多次,那么也需要这样一个数字。例如,我们来看下面的查找方法:
  Collection findLocaitonNamedOrNamedShorterThan(String name);
这个方法有一个EJB QL查询语句:
  SELECT OBJECT(l)
FROM Location AS l
WHERE l.name=?1
OR LENGTH(l.name)
此语句使用内建函数LENGTH返回一个String的长度。在任何情况下这个另类的查找方法都可找到那些有具体名字的地理位置,并将所有小雨提供名字长度的名字返回。我们看到?1展位副出现了不止一次,这是因为需要在两个地方将名字参数绑定到查询。
  EJB QL只定义了少数几个内建函数.在这些内建函数中,返回字符串的函数是CONTACT和SUBSTRING;返回数据的函数是LENGTH、ABS、SORT和LOCATE。LOCATE函数与String.indexOf(String str, int fromIndex)函数具有相同的功能。
EJB QL只定义了两个终结操作符——IS [NOT] EMPTY和[NOT] MEMBER OF。ANSI SQL中不存在着两个操作符等价物,但在OCL中却存在。
IS [NOT] EMPTY 操作符类似于OCL中的isEmpty操作符,可用来判断cmr字段返回的集合是否为空。例如,以下语句:
SELECT OBJECT(s)
FROM Skill AS s
WHERE s.jobs IS EMPTY

将没有任何职位需要的技能全部返回。这可以是SkillLocalHome接口的查询方法的查询,方法名字类似于findNotNeededSkills()。
实际上,这种查询也可用ANSI SQL语句描述,但需要一个字查询:
SELECT s.*
FROM Skill AS s
WHERE NOT EXISTS
(SELECT *
FROM JobSkill AS j
WHERE s.skill = j.skill)
[NOT]MEMBER OF操作符类似于OCL的include操作符。考虑一下下面JobLocalHome接口中的查询方法:
Collection findJobsRequiringSkill(SkillLocal skill) ;

相关的EJB QL查询如下:
SELECT OBJECT(j)
FROM Job AS j
WHERE ?1 MEMBER OF j.skills

同样,这条语句也可在ANSI SQL中实现,同样需要使用一个子查询:
SELECT j.*
FROM Job AS j
WHERE EXISTS
(SELECT *
FROM JobSkill AS s
WHERE j.customer = s.customer
AND j.ref = s.ref
AND s.skill = ?1)

更多内容
你可能听说过“OO/关系型阻抗错配”,即要处理对象必须示例每个对象,然后向此对象发送一条消息。另一方面,关系型理论共享某些公共属性的元素集合;要想有效地表示这些元素而不对其进行示例,则需要打破封装。
EJB QL为解决这些问题作了大量的工作。通过允许在面向集合的语法中表达查询,EJB容器在数据存储集为RDBMS时可轻松地将这些查询映射到ANSI SQL。另一方面,查找方面生成的实现仅返回对象或对象的集合。
然而,EJB QL确实有一些限制。例如,当构造EJB QL查询时,仅仅可使用bean之间声明的关联。将任意字段联合在一起(如ANSI SQL那样)是不可能的事情。例如,某些Customer(客户)同时还是Applicant(求职者),那么将无法使用诸如Applicant.name=Customer.name之类的条件来表示这些Customer。
大量的实例证明EJB QL没有(尚不如)ANSI SQL功能强大。例如,EJB QL不支持分组和汇总、排序、子查询和联合。随着EJB QL的不断成熟,这些功能会不断添加进来。尽管EJB QL不支持子查询,但由于IS[NOT] EMPTY和[NOT] MEMBER OF操作符的存在,我们不使用自查询也能实现相同的功能。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值