Utilisation du service DMS (Data Mediator Service) EJB pour l'accès aux données
Les étapes suivantes utilisent des exemples de codes pour décrire une instance simple de création de métadonnées de service DMS EJB.
Procédure
Exemple
- Utilisation d'arguments de requête avec le médiateur EJB.
Les exemples suivants vous indiquent comment définir les arguments de requête de votre médiateur Enterprise JavaBeans (EJB).
- Exemple simple
- Cette requête renvoie un datagraphe contenant plusieurs instances d'objet de données de type (nom Eclass) Emp. Les attributs de l'objet de données sont empid et name et leurs types de données correspondent aux types de zones CMP.
Le datagraphe renvoyé sérialisé au format XML se présente ainsi :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>
- Paramètres de requête
- Cet exemple montre comment utiliser des marqueurs de paramètre. Rappelez-vous que dans une requête d'EJB les marqueurs de paramètre sont symbolisés par un point d'interrogation suivi d'un chiffre (?n). Lors de l'appel de la méthode getGraph ( ) sur le médiateur d'EJB, vous pouvez éventuellement transmettre un tableau de valeurs. ?n fait référence à la valeur de parm[n-1]. Le tableau de valeurs peut également être transmis sur l'appel de fabrique de connexions pour créer le médiateur d'EJB. Les paramètres transmis avec getGraph( ) remplacent tous les paramètres transmis avec l'appel create.
select e.empid, e.name from Emp as e where e.salary > ?1
- Retour d'expressions et de méthodes
- Cet exemple montre que les attributs d'objet de données peuvent être les valeurs renvoyées par les expressions de requête. Les expressions de requête d'EJB sont notamment des expressions arithmétiques, de date et heure, de chemins, et des méthodes. Les arguments d'entrée et les valeurs de retour de ces méthodes sont strictement limités à la liste des types de données pris en charge (voir Syntaxe de la requête du médiateur d'EJB). Lorsqu'un objet de données contenant un attribut mis à jour est dérivé d'une expression, une exception se produit lors du processus applyChanges à moins que l'utilisateur fournisse un adaptateur de médiateur pour gérer la modification.
Les noms d'attribut d'objet de données sont dérivés des noms de zone CMP mais peuvent être remplacés en insérant le mot clé AS dans la requête. Lors de la spécification d'une expression, le mot clé AS doit toujours être utilisé pour attribuer un nom à l'expression.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
- Syntaxe *
- La notation e.* est un raccourci permettant de désigner toutes les zones CMP (mais pas les relations gérées par conteneurs) d'un EJB. La requête suivante a la même signification que e.empid, e.name e.salary, e.bonus.
select e.* from Emp as e
- Pas de clé primaire dans la clause select
- Cet exemple présente une requête qui ne renvoie pas la zone de clé primaire. Toutefois, à moins que l'objet de données ne contienne toutes les zones de clé primaire d'un EJB, le médiateur ne peut pas traiter les mises à jour du datagraphe. En effet, la clé primaire est nécessaire pour convertir les modifications en SQL ou pour convertir les références d'objet de données en références EJB. Une exception se produit lors de la tentative d'exécution de applyChanges.
select e.name, e.salary from Emp as e
- ORDER BY
- Les objets de données peuvent être triés.
Cette opération entraîne le tri des objets Dept par noms et le tri des objets Emp contenus dans chaque Dept par ordre décroissant de empid.select d.* from Dept d order by d.name select e.* from in(d.emps) e order by e.empid desc
- Parcours d'une relation à plusieurs valeurs
- Cette requête composée renvoie un datagraphe et les classes d'objet de données Dept et Emp. La forme du datagraphe reflète les expressions des chemin d'accès utilisées dans les clauses FROM.
Dans ce cas, Dept est le noeud racine du datagraphe et il existe une référence à plusieurs valeurs de Dept à Emp comme illustré :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>
- Informations supplémentaires sur les paramètres de requête
- Des conditions de recherche peuvent être spécifiées dans toute requête. Les arguments d'entrée valent pour toute la requête et peuvent être référencés d'après un numéro dans n'importe quelle requête composée. Dans l'exemple précédent, les arguments de requête transmis par l'appel create ou getGraph doivent se présenter dans l'ordre { 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
- Parcours d'un chemin avec relation à plusieurs valeurs
- La requête suivante parcourt le chemin composé des relations entre les EJB Dept.projs et Project.tasks et renvoie pour Dept, Emp et Project des objets de données contenant les zones CMP sélectionnées.
Le datagraphe résultant au format XML est présenté ci-dessous.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>
- Parcours de plusieurs chemins
- Voici une requête de médiateur qui renvoie un datagraphe des objets de données pour Dept avec les employés associés et un second chemin qui extrait les projets et tâches associés.
Le datagraphe renvoyé se présente ainsi :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>
- Parcours d'une relation à une seule valeur
- L'élément important à noter ici est que même si Emp est l'objet de données racine du graphe, plusieurs objets de données Emp seront associés au même objet de données Dept. Donc, à la différence des exemples précédents, le datagraphe n'a pas la forme d'une arborescence lorsque vous visualisez les instances d'objet de données ; il existe plusieurs objets de données racine Emp associés au même objet de données Dept. Mais, après tout, il s'agit d'un datagraphe et non d'une arborescence de données. Les requêtes du médiateur acceptent les expressions de chemin à valeur unique dans la clause FROM. C'est une nouveauté dans la syntaxe des requêtes standard d'EJB.
Le datagraphe au format XML se présente ainsi :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>
- Expressions de chemin dans la clause SELECT
- Cette requête est similaire à la précédente (elle renvoie des données relatives aux employés ainsi que le nom et le numéro du département), mais le datagraphe ne contient qu'un seul type d'objet de données (alors qu'il en contenait deux dans la précédente). Les zones deptno et name sont en lecture seule car elles résultent d'une expression de chemin de la clause SELECT et ne sont pas des zones CMP de l'EJB Emp.
select e.empid as EmplId , e.name as EmpName , e.dept.deptno as DeptNo , e.dept.name as DeptName from Emp as e
- Parcours d'une relation many:many
- La relation Emp à Task est considérée comme une relation many:many. La requête suivante extrait les employés, tâches et projets. Il n'existe qu'une seule occurrence d'un objet de données de tâche spécifique dans le datagraphe, même s'il peut être associé à plusieurs employés.
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
- Plusieurs liens entre les objets de données
- Le médiateur EJB vous permet d'extraire les données en fonction des relations et d'utiliser la commande XREL pour construire une ou plusieurs relations supplémentaires sur la base des données déjà extraites. Le médiateur permet aussi l'extraction des données en fonction du ASNname puis la construction d'une ou plusieurs relations sur la base des données extraites à l'aide de la commande XREL. La requête suivante extrait les services, les employés des différents services ainsi que les employés qui gèrent chaque service.
Les deuxième et troisième clauses select renvoient des instances de l'objet de données Emp. Il est possible que la même instance Emp soit extraite dans la relation d.emps et la relation d.manager. Le médiateur EJB crée une seule instance Emp mais crée les deux relations.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
La requête suivante est traitée comme suit. Les objets de données Dept sont créés à partir des données de la première requête. Les objets de données Emp sont créés à partir des données de la seconde requête. Dans le graphique, les relations sont alors construites pour toute relation utilisée dans la clause FROM ou un mot clé XREL. Lors de la construction de la relation, aucune donnée supplémentaire n'est extraite. Dans cet exemple, un employé qui travaille dans un service appelé Dev apparaît dans le datagaphe. Si cet employé gère un service appelé Sales, la référence manages est vide. Le service Dev a été extrait dans la première requête, et non le service 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
Les relations emps et manager sont construites en fonction des instances d'objet de données créées à partir des requêtes. Un employé dont le nom est "Dev" mais qui travaille dans le service "Sales" aura une relation de service nulle dans le graphique.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
L'exemple suivant présente l'extraction des objets de données pour tous les employés, projets et tâches pour un service donné, ainsi que la liaison des employés aux tâches.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
Si une tâche est assignée à un employé du service 42, alors ce lien s'affiche dans le datagraphe. Si la tâche est assignée à un employé qui ne fait pas partie du service 42, alors cette liaison n'apparaît pas dans le datagraphe car l'objet de données a été éliminé (filtrage) par la requête. Un mot clé XREL peut être suivi d'une ou plusieurs relations EJB. Les relations bidirectionnelles peuvent se référer à n'importe quel nom de rôle. La source et la cible de la relation peuvent être extraites par une ou plusieurs requêtes.
- Extraction des objets non associés
- La requête suivante extrait Dept et 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'
La requête suivante extrait Dept et Emps. Même s'il existe une relation entre Dept et Emp (à savoir mgr et emps), aucune relation n'est utilisée dans FROM ou XREL, et le graphique qui en résulte ne contient pas les valeurs de relation.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%'
- Extraction des relations nulles ou vides
- Cette requête renvoie les services qui n'ont pas d'employés ainsi que les employés qui ne font pas partie d'un service. Normalement, l'application doit assigner les employés à l'un des services. xrel a pour but de définir la relation e.dept (et le rôle inversé d.emps) dans le schéma de graphique.
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
- Paramètre d'entrée de collection
- Une collection de beans enterprise peut être transmise en tant qu'argument d'entrée au médiateur d'EJB et référencée dans la clause FROM. L'utilisation d'un paramètre de collection permet de construire un datagraphe à partir d'une collection utilisateur de beans enterprise déjà activés.
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
La requête indiquée se répète dans la collection de beans Dept et de beans Emp associés, appliquant les prédicats de la requête et construisant le graphique de données. Les valeurs sont obtenues à partir des valeurs actuelles des beans. Voici un exemple de programme utilisant un paramètre de collection d'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. }
- Utilisation de MediatorAdapter
Dans cet exemple, l'adaptateur traite des événements CREATE pour un objet de données EMP. Les attributs de nom et de salaire sont extraits de l'objet de données et transmis à la méthode create sur EmpLocalHome.
La méthode create renvoie une instance d'EJB Emp et la valeur de clé primaire est recopiée dans l'objet de données. L'appelant peut alors obtenir la valeur de clé générée. Après traitement, l'adaptateur renvoie la valeur true. L'adaptateur ignore toutes les autres modifications, qui sont traitées par le médiateur d'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(){} }