技术开发 频道

详解Enterprise JavaBeans查询语言之一

【IT168 技术文档】

  Enterprise JavaBeans查询语言(EJB QL)定义了容器管理持续化的finder方法和select方法的查询。作为SQL92的一个子集,EJB QL进行了扩展,它可以使用entity bean的抽象模式中定义的关联。一个EJB QL查询可以跨越封装在同一个EJB JAR文件中的所有相关的entity bean的抽象模式。
 
  你可以在entity bean中部署描述中定义EJB QL查询。典型的情况是,一个工具会将这些查询转换成低层数据存储所使用的查询语言。因为这种转换的存在,使用容器管理持续化的entity bean具有可移植性--它们的代码不受具体的数据存储的类型的影响。
 
下面列出了本文用到的一些术语的定义。
 
1、Abstract schema--抽象模式:一个entity bean的部署描述的一部分,它定义了bean的持续化字段和关联关系。
 
2、Abstract schema name--抽象模式名:在EJB QL查询中引用的一个逻辑命名。你需要为每个容器管理持续化的entity bean指定一个抽象模式名。
 
3、Abstract schema type--抽象模式类型:所有的EJB QL表达式都对应一个类型。如果表达式是一个抽象模式名,那么它的类型默认是定义了这个抽象模式名的entity bean的local接口。
 
4、Backus-Naur Form (BNF)--巴科斯-诺尔范式:一种描述高级语言语法的一种表示法。这一章的语法图表使用了BNF表示法。
 
5、navigation--跨越:在一个EJB QL表达式中对关联关系的使用。跨越操作符是一个句点。
 
6、path expression--路径表达式:一个跨越到相关entity bean的表达式。
 
7、persistent field--持续化字段:一个容器管理持续化的entity bean中的一个虚拟字段;它存储在一个数据库中。
 
8、relationship field--关联字段:一个容器管理持续化的entity bean中的一个虚拟字段;它确定了一个相关的entity bean。
 
简单的语法
 
  这里简要地描述了EJB QL的语法,这样你可以快速进入下面查询示例的学习。如果你要对此进行更深入的学习,请阅读完整的语法。
 
  一个EJB QL查询由三个子句组成:SELECT子句、FROM子句和WHERE子句,SELECT子句和FROM子句是必选的,而WHERE子句是可选的。下面是一个EJB QL查询的简单BNF定义:
 
EJB QL :: = select_clause
from_clause [where_clause]
 
  SELECT子句定义了对象的类型或查询的返回值。返回类型可是一个local接口、一个remote接口或是一个持续化字段。
 
  FROM子句通过声明一个或多个标识变量定义了查询的范围,这些标识变量可能会在SELECT子句和WHERE子句中被引用。一个标识变量反映了下列元素之一:
 
1、一个entity bean的抽象模式名
 
2、一个集合的一个成员,这个集合是一个一对多关系中的多端
 
  WHERE子句是一个限制查询找到的对象或数值的条件表达式。尽管它是可选的,但是绝大多数查询都会有一个WHERE子句。
 
简单的Finder查询
 
如果你对EJB QL不熟悉,这些简单的查询将有助于你尽快入门。
 
示例 1
 
SELECT OBJECT(p)
FROM Player p
 
获得的数据:所有队员。
 
Finder方法: findall()
 
说明:FROM子句声明了一个名为p的标识变量,其中省略了可选的AS关键字。如果使用了AS关键字,这个子句将是这样的:
 
FROM Player AS p
 
Player元素是PlayerEJB entity bean的抽象模式名。因为bean在LocalPlayerHome接口中定义了findall方法,所以这个查询返回的对象具有LocalPlayer类型。
 
示例 2
 
SELECT DISTINCT OBJECT(p)
FROM Player p
WHERE p.position = ?1
 
获得的数据:由finder方法的参数指定位置的队员。
 
Finder方法: findByPosition(String position)
 
说明:在一个SELECT子句中,在例如p这样的独立的标识变量前面要加OBJECT关键字。DISTINCT关键字排除了重复的数据。
 
WHERE子句通过检查队员的position这个PlayerEJB entity bean的持续化字段对获得的队员进行了限制。?1元素表示了了findByPosition方法中的输入参数。
 
示例 3
 
SELECT DISTINCT OBJECT(p)
FROM Player p
WHERE p.position = ?1
AND p.name = ?2
 
获得的数据:指定位置和姓名的队员。
 
Finder方法: findByPositionAndName(String position, String name)
 
说明:position元素和name元素是PlayerEJB entity bean的持续化字段。WHERE子句将这些字段与findByPositionAndName方法的输入参数进行比较。EJB QL使用一个后面带有整数的问号表示输入参数。第一个输入参数中?1,第二个是?2,依此类推。
 
跨越相关Bean的Finder查询
 
  在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
 
获得的数据:属于指定城市的运动队的队员。
 
Finder方法: findByCity(String city)
 
  说明:FROM子句声明了两个标识变量:p和t。p变量表示PlayerEJB entity bean,而t变量表示相关的TeamEJB bean。在t的声明中引用了之前声明的p变量。IN关键记号表示teams是一个相关bean的集合。p.teams表示式实现了从PlayerEJB bean到它的相关TeamEJB bean的跨越。p.teams表达式中的句点是跨越操作符。
 
  在WHERE子句中,标识变量city之前的句点是一个分隔符,而不是一个跨越操作符。严格说来,表达式可以跨越到关联字段(相关的bean),而不是持续化字段。要访问一个持续化字段,一个表达式必须使用句点作为分隔符。
 
  表达式不可以对作为集合的关联字段作更进一步的跨越。在一个表达式的语法中,collection-value字段是一个终结符。因为teams字段是一个集合,所以WHERE子句不可以指定 p.teams.city--这是一个非法的表达式。
 
示例 5
 
SELECT DISTINCT OBJECT(p)
FROM Player p, IN (p.teams) AS t
WHERE t.league = ?1
 
获得的数据:属于指定运动联盟的队员。
 
Finder方法: findByLeague(LocalLeague league)
 
  说明:这个查询中的表达式实现了两个关联关系的跨越。p.teams表达式跨越了PlayerEJB-TeamEJB关联关系,而t.league表达式跨越了TeamEJB-LeagueEJB关系。
 
  在其它示例中,输入参数是String对象,但是在这个示例中参数是一个类型为一个LocalLeague接口的对象。这个类型与WHERE的比较表达式中的league关联字段匹配。
0
相关文章