使用 EJB 数据介体服务来访问数据

下列步骤使用代码样本来描述有关如何创建 Enterprise JavaBeans (EJB) 数据介体服务 (DMS) 元数据的简单实例。

过程

  1. 介体实例是使用介体工厂 (com.ibm.websphere.sdo.mediator.ejb.MediatorFactory) 的某个 create 方法创建的,如以下示例所示
    import com.ibm.websphere.sdo.mediator.ejb.Mediator;
    import com.ibm.websphere.sdo.mediator.ejb.MediatorFactory;
    import com.ibm.webpshere.ejbquery.QueryException;
    import commonj.sdo.DataObject;
    
    try{
     String[] query =  { "select d.deptno,d.name from DeptBean as d" }; 
     Mediator m = MediatorFactory.getInstance().createMediator( query, null);
     DataObject root = m.getGraph();
    } catch (QueryException e) { ... } 
  2. createMediator 方法有三种不同的格式。自变量说明如下:
    createMediator( query, parms) 
    createMediator( query, parms, schema )
    createMediator( query, parms, schema,  typeMap,  pattern)
    表 1. createMediator 方法自变量. 下表说明了这些自变量:
    类型 自变量 描述
    字符串 query EJB 查询语句的数组
    对象 parms 查询语句的输入参数的值
    Eclass* 模式 根 DataObject 的 e 类
    Map* typeMap 从查询语句将 EJB 抽象模式名称映射至 e 类名称的 java.util.Map
    int* pattern 用于包含的模式
     
    仅当使用调用者提供的模式时,使用 *

示例

将查询自变量与 EJB 介体配合使用。

以下示例显示如何能够调整您的 Enterprise JavaBeans (EJB) 介体查询自变量。

简单示例
该查询返回包含多个实例的类型(Eclass 名称)为 Emp 的 DataObject 的 Datagraph。数据对象属性是 empidname,并且它们的数据类型对应于容器管理的持久性 (CMP) 字段类型。
select  e.empid, e.name 
from Emp as e 
where e.salary > 100
按如下所示已返回的 DataGraph 按其 XML 格式序列化:
<?xml version="1.0" encoding="ASCII"?>
<datagraph:DataGraphSchema xmlns:datagraph="datagraph.ecore">
<root>
<Emp empid="1003" name="Eric" />
<Emp empid="1004" name="Dave" />
</root>
</datagraph:DataGraphSchema>
查询参数
此示例显示了如何使用参数标记。重新调用 EJB 查询中参数标记的语法,会有问号后跟有数字的标记(?n)。在 EJB 介体上调用 getGraph ( ) 方法时,您可以可选地传递值的数组。?n 是指值 parm[n-1]。还可以在工厂调用上传递值的数组来创建 EJB 介体。getGraph( ) 上传递的参数覆盖 create 调用上传递的任何参数。
select  e.empid, e.name 
from Emp as e 
where e.salary > ?1 
返回表达式和方法
该示例描述可以是查询表达式的返回值的数据对象属性。EJB 查询表达式包括算术、日期时间、路径表达式和方法。输入自变量和方法的返回值限制为该列表中的支持数据类型(请参阅“EJB 介体查询语法”主题)。处理 applyChanges 期间,包含从表达式派生的更新属性的数据对象导致发生异常,除非用户提供了用于处理更改的介体适配器。
select  e.empid as employeeId, 
  e.bonus+e.salary as totalPay,  
  e.dept.mgr.name as managerNam, 
  e.computePension( ) as pension 
from Emp as e 
where e.salary > 100
数据对象属性名称是从 CMP 字段名派生的,但是可以使用查询中的 AS 关键字重设这些属性名称。当指定表达式时,应该总是使用 AS 关键字为该表达式给定一个名称。
* 语法
表示法 e.* 是一种指定 EJB 的所有 CMP 字段(但不是容器管理的关系)的简单快捷方法。以下查询与 e.empid, e.name e.salary, e.bonus 的作用相同。
select e.* from Emp as e
select 子句中没有主键
该示例显示不返回主键字段的查询。然而,除非数据对象包含 EJB 的所有主键字段,否则介体无法处理对 DataGraph 的更新。这是因为需要主键将更改转换为结构化查询语言 (SQL)、或者将 DataObject 引用转换为 EJB 引用。当尝试运行 applyChanges 时发生异常。
select e.name, e.salary from Emp as e
Order by
可以对 DataObject 进行排序。
select d.* from Dept d  order by d.name
select e.* from in(d.emps) e order by e.empid desc
这导致按名称对 Dept 对象进行排序,以及按 empid 对每个 Dept 中的 Emp 对象以降序排序。
浏览多值的关系
此复合查询返回具有 DataObject 类 DeptEmp 的 Datagraph。Datagraph 的形状影响 FROM 子句中使用的路径表达式。
select d.deptno, d.name, d.budget from Dept d  
			where d.deptno < 10 
select e.empid, e.name, e.salary  from in(d.emps) e 
			where e.salary > 10
在此事例中,Dept 是 Datagraph 中的根节点,并且存在从 DeptEmp 的多值引用,如下所示:
<?xml version="1.0" encoding="ASCII" ?> 
<datagraph:DataGraphSchema xmlns:datagraph="datagraph.ecore">
<root>
<Dept deptno="1" name="WAS_Sales" budget="500.0" 
   emps="//@root/@Emp.1 //@root/@Emp.0" /> 
<Dept deptno="2" name="WBI_Sales" budget="450.0" 
   emps="//@root/@Emp.3 //@root/@Emp.2" /> 
<Emp empid="1001" name="Rob" salary="100.0" EmpDept="//@root/@Dept.0" /> 
<Emp empid="1002" name="Jason" salary="100.0" EmpDept="//@root/@Dept.0" /> 
<Emp empid="1003" name="Eric" salary="200.0" EmpDept="//@root/@Dept.1" /> 
<Emp empid="1004" name="Dave" salary="500.0" EmpDept="//@root/@Dept.1" /> 
</root>
</datagraph:DataGraphSchema>
有关查询参数的更多信息
可以在任何查询上指定搜索条件。对于查询而言输入自变量是全局的,并且可以在复合查询的任何位置用数字引用这些参数。在上述示例中,create 或 getGraph 调用中传递的查询自变量应该按 { deptno value, salary value, deptno value } 顺序传递。
select d.* from Dept as d 
   where d.deptno between ?1 and ?3 
select e.* from in(d.emps) e  
   where e.salary < ?2
浏览具有多个关系的路径
以下查询浏览由 EJB 关系 Dept.projs 和 Project.tasks 组成的路径,并返回包含所选 CMP 字段的 Dept、Emp 和 Project 的 DataObject。
select d.deptno, d.name from Dept as d 
select p.projid  from in(d.projects) p 
select t.taskid, t.cost from  in (p.tasks) t
此处显示了得出的 XML 格式的 DataGraph。
<?xml version="1.0" encoding="ASCII" ?> 
<datagraph:DataGraphSchema xmlns:datagraph="datagraph.ecore">
<root>
<Dept deptno="1" name="WAS_Sales" projects="//@root/@Project.0" /> 
<Dept deptno="2" name="WBI_Sales" projects="//@root/@Project.1" /> 
<Project projid="1" ProjectDept="//@root/@Dept.0" 
      tasks="//@root/@Task.0   //@root/@Task.2 //@root/@Task.1" /> 
<Project projid="2" ProjectDept="//@root/@Dept.1" 
      tasks="//@root/@Task.3" /> 
<Task taskid="1" cost="50.0" TaskProject="//@root/@Project.0" /> 
<Task taskid="2" cost="60.0" TaskProject="//@root/@Project.0" /> 
<Task taskid="3" cost="900.0" TaskProject="//@root/@Project.0" /> 
<Task taskid="7" cost="20.0" TaskProject="//@root/@Project.1" /> 
</root>
</datagraph:DataGraphSchema>
浏览多个路径
此处是返回具有相关职员的 Dept 的 DataObject 的 DataGraph 的介体查询,以及检索相关项目和任务的第二个路径。
select d.deptno, d.name from Dept d 
select e.empid, e.name  from in(d.emps) e
select p.projid from in(d.projects) p 
select t.taskid, t.cost from in(p.tasks) where t.cost > 10
返回的 DataGraph 看起来为如下所示:
<?xml version="1.0" encoding="ASCII" ?> 
    <datagraph:DataGraphSchema xmlns:datagraph="datagraph.ecore">
    <root>
        <Dept deptno="1" name="WAS_Sales" projects="//@root/@Project.0" 
            emps="//@root/@Emp.1 //@root/@Emp.0" /> 
        <Dept deptno="2" name="WBI_Sales" projects="//@root/@Project.1" 
            emps="//@root/@Emp.3 //@root/@Emp.2" /> 
        <Project projid="1" ProjectDept = "//@root/@Dept.0"
            tasks="//@root/@Task.0 //@root/@Task.2 //@root/@Task.1" /> 
        <Project projid="2" ProjectDept="//@root/@Dept.1"
            tasks="//@root/@Task.3" /> 
        <Task taskid="1" cost="50.0" TaskProject="//@root/@Project.0" /> 
        <Task taskid="2" cost="60.0" TaskProject="//@root/@Project.0" /> 
        <Task taskid="3" cost="900.0" TaskProject="//@root/@Project.0" /> 
        <Task taskid="7" cost="20.0" TaskProject="//@root/@Project.1" /> 
        <Emp empid="1001" name="Rob" EmpDept="//@root/@Dept.0" /> 
        <Emp empid="1002" name="Jason" EmpDept="//@root/@Dept.0" /> 
        <Emp empid="1003" name="Eric" EmpDept="//@root/@Dept.1" /> 
        <Emp empid="1004" name="Dave" EmpDept="//@root/@Dept.1" /> 
  </root>
  </datagraph:DataGraphSchema>
浏览单值的关系
这里要指出的重要信息是即使 Emp 是图中的根数据对象,多个 Emp 数据对象也将与同一 Dept 数据对象相关。因此,与先前示例不同,当您查看数据对象实例时,数据图不是树形图;有多个根 Emp 对象与同一 Dept 对象相关。但是此时它毕竟是一个数据图,而不是数据树。注意,介体查询允许 FROM 子句中有单值路径表达式。这是标准 EJB 查询语法的更改。
select e.empid, e.name  from Emp e 
select d.deptno, d.name  from in(e.dept) d 
而 XML 格式的 DataGraph 按如下所示:
<?xml version="1.0" encoding="ASCII" ?> 
   <datagraph:DataGraphSchema xmlns:datagraph="datagraph.ecore">
   <root>
      <Emp empid="1001" name="Rob" dept="//@root/@Dept.0" /> 
      <Emp empid="1002" name="Jason" dept="//@root/@Dept.0" /> 
      <Emp empid="1003" name="Eric" dept="//@root/@Dept.1" /> 
      <Emp empid="1004" name="Dave" dept="//@root/@Dept.1" /> 
      <Dept deptno="1" name="WAS_Sales" DeptEmp="//@root/@Emp.1 //@root/@Emp.0" /> 
      <Dept deptno="2" name="WBI_Sales" DeptEmp="//@root/@Emp.3 //@root/@Emp.2" /> 
   </root>
   </datagraph:DataGraphSchema>
SELECT 子句中的路径表达式
此查询与先前描述的查询相似(两种查询都返回职员数据以及部门号和名称),但是注意,数据图只包含该查询中的一个数据对象类型(与先前相比,在先前的查询中包含两个数据对象类型)。字段 deptno 和 name 字段是只读的,这是因为它们是由 SELECT 子句的路径表达式生成的并且不是 Emp EJB 的 CMP 字段。
select  e.empid as EmplId , e.name as EmpName ,
		 e.dept.deptno as DeptNo , e.dept.name as DeptName
from Emp as e
浏览多对多关系
Emp 与 Task 之间的关系被认为是多对多关系。以下查询将检索职员、任务和项目。DataGraph 中的任何特定任务 DataObject 都将只出现一次,尽管它可能与许多职员相关。
select e.empid, e.name from Emp as e
select t.taskid, t.description from in(e.tasks) as t
select p.projid, p.cost from in(t.proj) as p
数据对象之间的多个链接
EJB 介体使您可以根据关系来检索数据,并使用 XREL 命令来根据已经检索的数据来构造一个或多个附加关系。介体还允许根据 ASNname 来检索数据,然后使用 XREL 命令并根据已检索的数据来构造一个或多个关系。以下查询将检索各个部门、在各个部门工作的职员以及负责管理各个部门的职员。
select d.deptno, d.name from Dept d where d.name like ‘%Dev%'
select e.empid, e.name from in (d.emps) as e
select m.empid, m.name from in(d.manager) as m
第二个和第三个 select 子句都将返回 Emp DataObject 的实例。通过 d.emps 关系和 d.manager 关系有可能检索到同一 Emp 实例。这种情况下,EJB 介体将只创建一个 Emp 实例,但是将同时创建这两种关系。
以下查询将按如下所示进行处理。将根据第一个查询中的数据来创建 Dept DataObject。将根据第二个查询中的数据来创建 Emp DataObject。然后,会为 FROM 子句或 XREL 关键字中使用的任何关系构造图中的关系。在构造关系期间,不会检索其他数据。在此示例中,一个在 Dev 部门工作的职员将出现在 DataGraph 中。如果此职员负责管理 Sales 部门,那么 manages 引用为空。在第一个查询中将检索 Dev 部门,而不是 Sales 部门。
select d.deptno, d.name from Dept d where d.name like ‘%Dev%'
select e.empid, e.name from in (d.emps) as e xrel d.manager
emps 和 manager 关系是根据从这些查询中创建的 DataObject 实例来构造的。名为“Dev”但是在“Sales”部门工作的员工在图中将具有空的 dept 关系。
select d.deptno, d.name from Dept d where d.name like ‘%Dev%'
select e.empid, e.name from Emp e where e.name like ‘Dev%' xrel d.emps, d.manager
下一个示例显示为给定部门的所有职员、项目和任务检索数据对象,还显示职员与任务之间的链接。
select d.deptno from Dept d where d.deptno = 42
select e.empid from in(d.emps) e  
select p.projid from in(d.projs) p 
select t.* from in(p.tasks) t xrel e.tasks

如果将一项任务分配给 42 部门中的一个职员,那么该链接将出现在数据图中。如果将该任务分配给一个不属于 42 部门的职员,那么该链接不会出现在数据图中。这是因为该数据对象被查询过滤掉了。XREL 关键字后面可以跟一个或多个 EJB 关系。双向关系可以表示任一角色名称。必须通过一个或多个查询来检索关系的源和目标。

检索不相关的对象
以下查询将检索 Dept 和 Task。
select d.deptno, d.name from Dept d where d.name like ‘%Dev%'
select t.taskid, t.startDate from Task t where t.startDate > ‘2005'
以下查询将检索 Dept 和 Emp。尽管 Dept 与 Emp 之间存在一些关系(即,mgr 和 emps),但是在 FROM 或 XREL 中不会使用任何一种关系,因此,获得的图中不包含关系值。
select d.deptno, d.name from Dept d where d.name like ‘%Dev%'
select e.empid, e.name from Emp e where e.dept.name like ‘%Dev%'
检索 NULL 或空关系
此查询将返回不包含任何职员的部门以及不属于任何部门的职员。可能应用程序想对其中一个部门分配职员。XREL 的用途是将 e.dept 关系(以及反向角色 d.emps)定义到图模式中。
select d.deptno, d.name from Dept d where d.emps is empty
select e.empid, e.name from Emp e where e.dept is null xrel e.dept
收集输入参数
可以将企业 Bean 的集合作为输入自变量传递到 EJB 介体并可以在 FROM 子句中引用该集合。使用集合参数满足从已激活的企业 Bean 的用户集合构造数据图的需求。
select d.deptno, d.name from ((Dept) ?1) as d
select e.empid, e.name from in(d.emps) as e where e.salary > 10
通过应用查询谓词并构造数据图,给定的查询对 Dept Bean 及相关 Emp Bean 的集合执行迭代。将从 Bean 的当前值获取值。使用 EJB 集合参数的程序的示例。
// this method runs in an EJB context and within a transaction scope   
public DataGraph myServiceMethod() { 
      InitialContext ic = new InitialContext();
      DeptLocalHome deptHome = ic.lookup("java:comp/env/ejb/Dept");
      Integer deptKey = new Integer(10);
      DeptEJB dept = deptHome.findByPrimaryKey( deptKey));
      Iterator i = dept.getEmps().iterator();
      while (i.hasNext()) {
        EmpEJB e = (EmpEJB)i.next();
        e.setSalary( e.getSalary() * 1.10); // give everyone a 10% raise 
      }

      // create the query collection parameter
      Collection c = new LinkedList();
      c.add(dept);
      Object[] parms = new Object[] { c};  // put ejb collection in parm array.

      // collection containing the dept EJB is passed to EJB Mediator

      String[] query = new String[] 
      { "select d.deptno, d.name from ((Dept)?1 ) as d", 
          "select e.empid, e.name, e.salary " +
          " from in (d.employees) as e", 
          "select p.projno, p.name from in (d.projects) as p" };

      Mediator m = EJBMediatorFactory.getInstance().createMediator(query, parms);
      DataGraph dg = m.getGraph();
      return dg;
      // the DataGraph contains the updated and as yet uncommitted 
      // salary information.  Dept and Emp data is fetched through
      // EJB instances active in the EJBContainer. 
      // Project data is retrieved from database using
      // container managed relationships.  
   }
使用 MediatorAdapter

在此示例中,适配器处理 EMP 数据对象的 CREATE 事件。从数据对象中抽取名称和薪水值,并将其传递到 EmpLocalHome 上的创建方法。

create 方法返回 Emp EJB 的实例并且将主键值复制回 DataObject。然后,调用者可以获得生成的键值。处理后,适配器返回值 true。适配器忽略所有其他更改,并且由 EJB 介体来处理这些更改。

package com.example;
import com.ibm.websphere.sdo.mediator.ejb.*;
import javax.naming.InitialContext;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.DataGraph;
import commonj.sdo.ChangeSummary;

// example of Adapter class calling a EJB create method.

public class SalaryAdapter implements MediatorAdapter{

  ChangeSummary log = null;
  EmpLocalHome empHome = null;

  public boolean applyChange(DataObject object,  int phase){

		if (object.getType().getName().equals("Emp")
		     && phase == MediatorAdapter.CREATE){
			try{
				String name = object.getString("name");
				double salary = object.getDouble("salary");
				EmpLocal emp = empHome.create(name, salary);
				object.set("empid", emp.getPrimaryKey() ); // set primary key in SDO
				return true;	
      } catch(Exception e){ // error handling code goes here 
      }
		}
		return true; 
  }

  public void init (ChangeSummary log){ 
      try {
        this.log = log;
        InitialContext ic = new InitialContext();
        empHome = (EmpLocalHome)ic.lookup(	"java:comp/env/ejb/Emp");
      } catch (Exception e) { // error handling code goes here
      }
  }

  public void end(){}
}

指示主题类型的图标 任务主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tejb_ejbmeduse
文件名:tejb_ejbmeduse.html