EJB Data Mediator Service für Datenzugriff verwenden
Die folgenden Schritte beschreiben anhand von Codebeispielen das Erstellen der Metadaten für den EJB Data Mediator Service (DMS).
Vorgehensweise
Beispiel
- Abfrageargumente mit EJB-Mediator verwenden
Die folgenden Beispiele veranschaulichen, wie Sie die Abfrageargumente für Enterprise JavaBeans (EJB) Mediator optimieren können.
- Einfaches Beispiel
- Diese Abfrage gibt einen DataGraph mit mehreren Instanzen von DataObjects des Typs (Eclass-Name) Emp zurück. Die Datenobjektattribute sind empid und name. Die Datentypen dieser Attribute entsprechen den CMP-Feldtypen.
Der zurückgegebene und im XML-Format serialisierte DataGraph sieht wie folgt aus:select e.empid, e.name from Emp as e where e.salary > 100
<?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>
- Abfrageparameter
- Dieses Beispiel demonstriert die Verwendung von Parametermarken. Wie Sie sich erinnern werden, haben Parametermarken in einer EJB-Abfrage die Syntax ?n (Fragezeichen, gefolgt von einer Zahl). Wenn Sie die Methode getGraph ( ) für den EJBMediator aufrufen, können Sie optional ein Array mit Werten übergeben. ?n bezieht sich auf den Wert von parm[n-1]. Das Array mit Werten kann auf mit dem Factoryaufruf zum Erstellen des EJBMediator übergeben werden. Mit getGraph( ) übergebene Parameter setzen die mit dem Aufruf von create übergebenen Parameter außer Kraft.
select e.empid, e.name from Emp as e where e.salary > ?1
- Rückgabe von Ausdrücken und Methoden
- Dieses Beispiel zeigt, dass die Datenobjektattribute Rückgabewerte von Abfrageausdrücken sein können. Zu den EJB-Abfrageausdrücken gehören arithmetische Ausdrücke, Date-Time-Ausdrücke, Pfadausdrücke und Methoden. Eingabeargumente und Rückgabewerte von Methoden sind auf die Liste der unterstützten Datentypen beschränkt. Lesen Sie hierzu den Artikel "Abfragesyntax für EJB Mediator". Ein Datenobjekt, das ein aus einem Ausdruck abgeleitetes aktualisiertes Attribut enthält, führt während der Verarbeitung von applyChanges zu einer Ausnahme, wenn der Benutzer keinen MediatorAdapter für die Handhabung der Änderung angegeben hat.
Die Namen von Datenobjektattributen werden aus den CMP-Feldnamen abgeleitet, können jedoch mit dem Schlüsselwort AS in der Abfrage überschrieben werden. Wenn Sie einen Ausdruck angeben, sollten Sie immer das Schlüsselwort AS verwenden, um dem Ausdruck einen Namen zu geben.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
- Syntax mit *
- Die Schreibweise e.* ist eine Kurzform für die Angabe aller CMP-Felder (jedoch nicht der containergesteuerten Beziehungen) einer EJB. Die folgende Abfrage hat dieselbe Bedeutung wie e.empid, e.name e.salary, e.bonus.
select e.* from Emp as e
- Kein Primärschlüssel in SELECT-Klausel
- Dieses Beispiel zeigt eine Abfrage, die nicht das Primärschlüsselfeld zurückgibt. Solange das Datenobjekt nicht alle Primärschlüsselfelder für eine EJB enthält, kann der Mediator jedoch keine Updates für den DataGraph verarbeiten. Dies liegt daran, dass der Primärschlüssel für die Umsetzung der Änderungen in SQL oder die Konvertierung von DataObject-Referenzen in EJB-Referenzen erforderlich ist. Wenn versucht wird, applyChanges auszuführen, tritt eine Ausnahme ein.
select e.name, e.salary from Emp as e
- 'ORDER BY'-Klausel
- DataObjects können sortiert werden.
Dies bewirkt eine Sortierung der Dept-Objekte nach Namen und der Emp-Objekte innerhalb jedes Dept-Objekts nach empid in absteigender Reihenfolge.select d.* from Dept d order by d.name select e.* from in(d.emps) e order by e.empid desc
- Navigation in einer Beziehung mit mehreren Werten
- Diese Verbundabfrage gibt einen DataGraph mit den DataObject-Klassen Dept und Emp zurück. Die Form des DataGraph spiegelt die in den FROM-Klauseln verwendeten Pfadausdrücke wider.
Dept ist in diesem Fall der Stammknoten im DataGraph. Wie nachfolgend gezeigt gibt es von Dept auf Emp eine Referenz mit mehreren Werten: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
<?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>
- Weitere Informationen zu Abfrageparametern
- Für jede Abfrage können Suchbedingungen angegeben werden. Die Eingabeparameter sind globale Parameter für die Abfrage und können an beliebiger Stelle der Verbundabfrage nach Nummer referenziert werden. Im obigen Beispiel sollten die im Aufruf von create oder getGraph übergebenen Abfrageargumente die Reihenfolge { deptno-Wert, salary-Wert, deptno-Wert } haben.
select d.* from Dept as d where d.deptno between ?1 and ?3 select e.* from in(d.emps) e where e.salary < ?2
- Navigation auf einem Pfad mit mehreren Beziehungen
- Die folgende Abfrage navigiert auf dem Pfad, der sich aus den EJB-Beziehungen Dept.projs und Project.tasks zusammensetzt und DataObjects für Dept, Emp und Project zurück, die ausgewählte CMP-Felder enthalten.
Das resultierende Datendiagramm im XML-Format sehen Sie hier: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 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>
- Navigation auf mehreren Pfaden
- Nachfolgend sehen Sie eine Mediator-Abfrage, die einen DataGraph mit DataObjects für Dept mit den zugehörigen employees zurückgibt, und einen zweiten Pfad, der die zugehörigen Projekte und Tasks abruft.
Der zurückgegebene DataGraph sieht wie folgt aus: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
<?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>
- Navigation in einer Beziehung mit einem Wert
- Hier ist als besonders wichtig anzumerken, dass obwohl Emp das Stammdatenobjekt im Diagramm ist, einem Dept-Datenobjekt mehrere Emp-Datenobjekte zugeordnet sind. Im Gegensatz zu den vorherigen Beispielen hat das Datendiagramm nicht die Form einer Baumstruktur, wenn Sie sich die Datenobjektinstanzen ansehen. Es gibt mehrere Stamm-Emp-Objekte, die einem Dept-Objekt zugeordnet sind. Es handelt sich hier um ein Datendiagramm und nicht um einen Datenstrukturbaum. Beachten Sie, dass in der FROM-Klausel von Mediator-Abfragen Pfadausdrücke mit nur einem Wert zulässig sind. Dies ist eine Abweichung von der Standard-EJB-Abfragesyntax.
Der DataGraph im XML-Format sieht wie folgt aus:select e.empid, e.name from Emp e select d.deptno, d.name from in(e.dept) d
<?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>
- Pfadausdrücke in der SELECT-Klausel
- Diese Abfrage ähnelt der vorherigen (beide Abfragen geben Mitarbeiterdaten mit Abteilungsnummer und Namen zurück). Das Datendiagramm enthält in dieser Abfrage jedoch nur einen Datenobjekttyp (und nicht zwei wie in der vorherigen Abfrage). Die deptno-Felder und das Namensfeld sind schreibgeschützt, weil sie das Ergebnis eines Pfadausdrucks in der SELECT-Klausel und keine CMP-Felder der Emp-EJB sind.
select e.empid as EmplId , e.name as EmpName , e.dept.deptno as DeptNo , e.dept.name as DeptName from Emp as e
- Navigation in einer N:M-Beziehung
- Die Emp-Task-Beziehung ist eine N:M-Beziehung. Die folgende Abfrage ruft Mitarbeiter (employees), Tasks und Projekte ab. Es gibt jeweils nur ein Vorkommen eines bestimmten Task-DataObject im DataGraph, selbst wenn dieses mehreren Mitarbeitern zugeordnet sein kann.
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
- Mehrere Verbindungen zwischen Datenobjekten
- Mit dem EJB Mediator können Sie Daten basierend auf Beziehungen abrufen und den Befehl XREL verwenden, um eine oder mehrere zusätzliche Beziehungen basierend auf den bereits abgerufenden Daten erstellen. Außerdem unterstützt der Mediator das Abrufen von Daten basierend auf dem ASNname und die anschließende Erstellung einer oder mehrerer Beziehungen basierend auf den mit dem Befehl XREL abgerufenden Daten. Die folgende Abfrage ruft Abteilungen (departments), Mitarbeiter (employees), die in den Abteilungen arbeiten, und Mitarbeiter ab, die die Abteilungen verwalten.
Die zweite und dritte select-Klausel geben beide Instanzen des DataObject Emp zurück. Es ist möglich, dass durch die Beziehung d.emps und die die Beziehung d.manager dieselbe Emp-Instanz abgerufen wird. Der EJB-Mediator erstellt eine Emp-Instanz, erstellt aber beide Beziehungen.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
Die folgende Abfrage wird wie folgt verarbeitet. DataObjects vom Typ Dept werden aus den Daten in der ersten Abfrage erstellt. DataObjects vom Typ Emp werden aus den Daten in der zweiten Abfrage erstellt. Anschließend werden für alle Beziehungen, die in der FROM-Klausel oder in einem XREL-Schlüsselwort verwndet werden, Beziehungen im Graphen erstellt. Während der Erstellung der Beziehungen werden keine weiteren Daten abgerufen. In diesem Beispiel erscheint ein Mitarbeiter, der in der Abteilung Dev arbeitet, im DataGraph. Wenn dieser Mitarbeiter eine Abteilung mit dem Namen Sales verwaltet, ist die Referenz manages leer. In der ersten Abfrage wurde die Abteilung Dev und nicht die Abteilung Sales abgerufen.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
Die Beziehung zwischen emps und manager wird basierend auf den von den Abfragen erstellten DataObject-Instanzen gebildet. Ein Mitarbeiter mit dem Namen "Dev", der in der Abteilung "Sales" arbeitet, hat im Graphen keine Beziehung zu 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
Das nächste Beispiel zeigt den Abfruf von Datenobjekten für alle Mitarbeiter, Projekte und Tasks für eine bestimmte Abteilung und die Verknüpfung von Mitarbeitern mit Tasks.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
Wenn eine Task einem Mitarbeiter in Abteilung 42 zugeordnet ist, erscheint diese Verknüpfung im Datengraph. Wenn die Task einem Mitarbeiter in einer anderen Abteilung als 42 zugeordnet ist, erscheint diese Verknüpfung nicht im Datengraphen, weil das Datenobjekt von der Abfrage gefiltert wurde. Einem XREL-Schlüsselwort können eine oder mehrere EJB-Beziehungen folgen. Bidirektionale Beziehungen können auf jeden Rollennamen verweisen. Quelle und Ziel der Beziehung müssen mit einer oder mehreren Abfragen abgerufen werden.
- Nicht zusammengehörige Objekte abrufen
- Die folgende Abfrage ruft Dept und Task ab.
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'
Die folgende Abfrage ruft Dept und Emps ab. Obwohl es Beziehungen zwischen Dept und Emp (mgr und emps) gibt, wird keine Beziehung in FROM oder XREL verwendet. Deshalb enthält der erstellte Graph auch keine Beziehungswerte.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%'
- Nicht vorhandene oder leere Beziehungen abrufen
- Diese Abfrage gibt Abteilungen zurück, die keine Mitarbeiter haben, oder Mitarbeiter ohne Abteilung zurück. Es ist anzunehmen, dass die Anwendung die Mitarbeiter einer der Abteilungen zuordnen möchte. Mit XREL wird die Beziehung e.dept (und die umgekehrte Beziehung d.emps) im Graphenschema definiert.
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
- Collection-Eingabeparameter
- Eine Gruppe von Enterprise-Beans kann als Eingabeargument an den EJB Mediator übergeben und in der FROM-Klausel referenziert werden. Mit der Verwendung eines Collection-Parameters wird die Anforderung erfüllt, ein Datendiagramm aus einer benutzerdefinierten Gruppe bereits aktivierter Enterprise-Beans zu konstruieren.
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
Die angegebene Abfrage geht die Gruppe der Dept-Beans und zugehörigen Emp-Beans durch, wendet die Abfrageprädikate an und konstruiert das Datendiagramm. Es werden die aktuellen Werte der Beans verwendet. Beispiel für ein Programm mit einem EJB-Collection-Parameter:// Diese Methode wird in einem EJB-Kontext innerhalb des Geltungsbereichs einer Transaktion ausgeführt. public DataGraph meineServicemethode() { 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); // Erhöhung um 10 % für alle } // Erstellen des Collection-Parameters der Abfrage Collection c = new LinkedList(); c.add(dept); Object[] parms = new Object[] { c}; // EJB-Gruppe wird in Parameter-Array gestellt // Die Gruppe mit der dept-EJB wird an den EJB Mediator übergeben. 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; // Der DataGraph enthält die aktualisierten und noch nicht übergebenen // Gehaltsinformationen. Die Dept- und Emp-Daten werden über EJB- // Instanzen, die im EJBContainer aktiv sind, abgerufen. // Projektdaten werden mittels containergesteuerter Beziehungen // aus der Datenbank abgerufen. }
- MediatorAdapter verwenden
In diesem Beispiel verarbeitet der Adapter CREATE-Ereignisse für ein EMP-Datenobjekt. Die Attribute "name" und "salary" werden aus dem Datenobjekt extrahiert und an die Methode create von EmpLocalHome übergeben.
Die Methode create gibt eine Instanz der Emp-EJB zurück, und der Primärschlüsselwert wird zurück in das Datenobjekt kopiert. Der Aufrufende kann dann den generierten Schlüsselwert abrufen. Nach Abschluss der Verarbeitung gibt der Adapter den Wert true zurück. Alle anderen Änderungen werden vom Adapter ignoriert und vom EJB-Mediator verarbeitet.
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; // Beispiel für eine Adapterklasse, die eine EJB-Methode create aufruft 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() ); // Primärschlüssel in SDO setzen return true; } catch(Exception e){ // Code für Fehlerbehandlung } } 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) { // Code für Fehlerbehandlung } } public void end(){} }