CMP Bean’s EJB QL
Introduction:
考虑customer-order-orderDetails的数据库表的一般的情况,下面是关于这3张表他们彼此之间的关系:
Tables 1: Customers Table 2: Order Table 3: orderDetails
customerId
|
CompanyName
|
Address
|
City
|
Region
|
OrderID
|
customerId
|
orderDate
|
Shipment
|
shipmentAdd
|
orderID
|
productId
|
Quantity
|
Price
|
问题:
1. 找出所有住在“New York”的客户。
2. 找出所有以“ER”开头的客户的名字。
3. 找出定单编号是‘1832’的客户。
4. 找出所有在’12/12/2001’ 和 ‘3/12/2002’.之间发出定单的客户。
5. 找出所有订购了’XYZ’产品的客户。
l CustomersEJB表示Customers CMP实体bean的类名
.
.
l Customers在CustomersEJB CMP的实体bean里面是表示一个抽象的表名.
.
.
1. find all customers who are living in “New York” city
按SQL语法的写法:
Select customer.companyName from customer where customer.city =’New York’
CMP实体Bean我们使用EJB QL语言的写法:
SELECT OBJECT(C) FROM Customers AS c WHERE c.city =’New York’.
FROM 子句:
l 所有别名必须定义在FROM字句里,并且在SELECT和WHERE字句里使用。
l 别名不能是标识符或者是下面的类型的名字:
• abstract-schema-name
• ejb-name
reserved identifiers are: SELECT, FROM, WHERE, DISTINCT, OBJECT,NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN, LIKE, IN, AS, UNKNOWN [18] , EMPTY, MEMBER, OF and IS.
WHERE 子句 :
l WHEREe字句必须使用在FROM字句里面定义的别名
l WHERE字句能够使用输入的参数,因而你能够写出QL的查询像这样:
SELECT OBJECT(c) FROM Customers AS c WHERE c.city = ?1
?1表示输入的第一个参数
SELECT 子句 :
SELECT字句表示一个查询结果。他包含一个范围变量,这个范围变量在一个实体Bean上面是一个抽象的表的类型,或者是一个表达式。
在ejb-jar文件里怎么定义一个abstract-schema-name:下面abstract-schema-name用黑体表示出来了
<ejb-jar>
<enterprise-beans>
<entity>
<display-name>CustomersEJB</display-name>
<ejb-name>CustomersEJB</ejb-name>
<home>com.bharat.ejbql.CustomersEJBRemoteHome</home>
<remote>com.bharat.ejbql.CustomersEJBRemote</remote>
<ejb-class>com.bharat.ejbql.CustomersEJBBean</ejb-class>
<persistence-type>Container</persistence-type>
表示是一个由容器管理的CMP的实体Bean
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>Customers</abstract-schema-name>
<cmp-field>
<field-name>customerName</field-name>
</cmp-field>
<cmp-field>
<field-name>city</field-name>
</cmp-field>
………..
others table fields
………..
在QL中我们要怎么使用abstract-schema-name
l 在我们定义的实体Bean的finder方法中,它不是一个唯一被使用的abstract-schema-name,在ejb-jar文件中你能够使用所有已经定义了的实体Bean的abstract-schema-name
l finder方法的返回值必须是我们已经定义的实体Bean的类型
l 接下来让我们为一个实体Bean定义一个finder()或者是一个select(),请注意下面几点:
l Finder()都定义在home接口里面,因而它们能够暴露在客户端被Bean调用
l Select()都被定义在bean的里面,所以他们只能在bean的内部使用
l 定义一个finder()的语法:
find<METHOD-NAME>
因而finder()可以像这样子定义:
Publicjava.util.Collection findByCity(java.lang.String city) throws RemoteException , FinderException.
要注意的两点:
l 我们的finder()接收String类型的参数并且抛出RemoteException and FinderException
l 方法的返回值是java.util.Collection.
完成上面的QL:
<query>
<query-method>
<method-name>findByCity</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<result-type-mapping>Local</result-type-mapping>
<ejb-ql>
SELECT OBJECT(c) FROM Customers AS c WHERE c.city = ?1
</ejb-ql>
</query>
到目前为止我们已经完成了我们第一个查询。在下面的查询中,你可以参考我们已经完成的查询的配置信息。我们不会重复这些配置信息,让我们开始进入第2个问题。
2.Find all customers whose companyName start with “ER”.
EJB QL :
SELECT OBJECT(c) Customers AS c WHERE c.companyName LIKE ‘ER%’.
类似的你也可以使用NOT LIKE:
SELECT OBJECT(c) Customers AS c WHERE c.companyName NOT LIKE ‘ER%’.
3 . find customer with orderID ‘1832’ ..(一对多关系的配置)
先让我们定义ejb-jar的配置信息,它绑定了CustomersEJB和OrdersEJB:
<relationships>
<ejb-relation>
<ejb-relation-name>customersEJB-ordersEJB</ejb-relation-name>
<ejb-relationship-role>(customersEJB的关系配置)
<description>customersEJB</description>
<ejb-relationship-role-name>
CustomersEJBRelationshipRole
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<description>customersEJB</description>
<ejb-name>CustomersEJB</ejb-name>
</relationship-role-source>
<cmr-field>
<description>ordersEJB</description>
<cmr-field-name>ordersEJB</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
要注意的地方: :
l 在Customers-Orders CMP beans.中我们配置了一个一对多关系。
这样我们就可以写出关联2个表的QL语句了:
SELECT OBJECT(c) FROM Customers AS c , IN(c.ordersEJB) o WHERE o.orderid = ?1
4. Find all customers who have given order between ’12/12/2001’ and ‘3/12/2002’ .
我们使用相同的关系映射在Customers-Orders获得查询结果。这里我们将在WHERE字句中使用BETWEEN操作符:
SELECT OBJECT(c) FROM Customers AS c , IN(c.ordersEJB) o WHERE o.orderDate BETWEEN ?1 AND ?2
在这个QL语句中返回的类型是一个集合的类型,它包含所有的在过去的这个事段中发出orders(定单)的customers(客户)的信息,但是在这个时段中可能有相同的customers发出了orders。我们能够限制结果不包含相同的customers:
l 在下面的SELECT子句中使用DISTINCT:
SELECT DISTINCT c FROM Customers AS c WHERE c.ordersEJB.orderid = ?1
l 定义一个finder()的返回值为java.util.Set代替java.util.Collection:
Public java.util.Set findByDateDiff(java.sql.Date start, java.sql.Date end) throws RemoteException , FinderException
如果你想返回的结果是不在那个时段发出orders的Customers的信息。我们可以使用NOT BETWEEN代替BETWEEN。
如果你没有使用上面的操作符,可以对照这些操作符的使用: > , < , >= ,<= ,<>
5. Find all customers who give order for product with productID of ?.
在这个例子中查询Customers的时候3张表都被调用了,所以在这个查询语句中,我们在使用了Order-Customer 表的关系映射中同样要加入 Orders和OrderDetails表的关系映射:
SELECT OBJECT(c) FROM Customers AS c , IN(c.ordersEJB) l , IN(l.orderDetailsEJB) od WHERE od.productid = ?1
这里的orderDetailsEJB已经在cmr-frield中关联了Orders 和 OrderDetails表。