Utilización de Data Mediator Service de EJB para acceso a datos
En los pasos siguientes se utilizan ejemplos de código para describir una instancia simple de cómo crear los metadatos DMS (Data Mediator Service) del EJB (Enterprise JavaBeans).
Procedimiento
Ejemplo
- Utilización de argumentos de consulta con el mediador de EJB
Los siguientes ejemplos muestran cómo puede ajustar los argumentos de consulta del mediador de EJB (Enterprise JavaBeans).
- Ejemplo sencillo
- Esta consulta devuelve un DataGraph que contiene varias instancias de DataObjects de tipo (nombre de Eclass) Emp. Los atributos de objeto de datos son empid (idempleado) y name (nombre) y sus tipos de datos corresponden a los tipos de campo CMP (persistencia gestionada por contenedor).
El DataGraph serializado devuelto en formato XML se parece a esto: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>
- Parámetros de consulta
- Este ejemplo muestra cómo se pueden utilizar los marcadores de parámetro. Recuerde que la sintaxis de marcadores de parámetro de consultas EJB es un símbolo de cerrar interrogación seguido de un número (?n). Cuando llama al método getGraph ( ) en el EJBMediator, puede pasar de modo opcional una matriz de valores. ?n hace referencia al valor de parm[n-1]. La matriz de valores también se puede pasar en la llamada a factory para crear el EJBMediator. Los parámetros pasados en getGraph( ) alteran temporalmente los parámetros pasados en la llamada a create.
select e.empid, e.name from Emp as e where e.salary > ?1
- Devolución de expresiones y métodos
- Este ejemplo ilustra que los atributos de objeto de datos pueden ser valores devueltos de expresiones de consulta. Las expresiones de consulta de EJB incluyen expresiones aritméticas, de fecha y hora, de vía de acceso y métodos. Los argumentos de entrada y los valores de retorno de los métodos quedan restringidos a la lista de tipos de datos soportados. Consulte el tema sobre la sintaxis de consulta del mediador de EJB. Los objetos de datos que contienen atributos actualizados derivados de expresiones provocan excepciones durante el proceso de applyChanges a no ser que el usuario haya proporcionado un MediatorAdapter para manejar el cambio.
Los nombres de atributo de objeto de datos se derivan de los nombres de campo CMP pero se pueden alterar temporalmente utilizando la palabra clave AS en la consulta. Cuando especifica una expresión, debería utilizar siempre la palabra clave AS para dar un nombre a la expresión.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
- Sintaxis de *
- La notación e.* es un fragmento abreviado para especificar todos los campos CMP (pero no las relaciones gestionadas por contenedor) de los EJB. La consulta siguiente significa lo mismo que e.empid, e.name e.salary, e.bonus.
select e.* from Emp as e
- Sin clave primaria en la cláusula SELECT
- Este ejemplo muestra una consulta que no devuelve el campo de clave primaria. No obstante, a no ser que el objeto de datos contenga todos los campos de clave primaria para un EJB, el mediador no podrá procesar las actualizaciones en el DataGraph. Esto es porque es necesaria la clave primaria para traducir los cambios en SQL (Lenguaje de consulta estructurada) o para convertir referencias de DataObject a referencias de EJB. Se produce una excepción cuando applyChanges intenta realizar la ejecución.
select e.name, e.salary from Emp as e
- Order by
- Los DataObjects se pueden ordenar.
Esto provoca que los objetos Dept se ordenen por nombre y los objetos Emp dentro de cada Dept se ordenen por empid en orden descendente.select d.* from Dept d order by d.name select e.* from in(d.emps) e order by e.empid desc
- Navegación por relaciones de varios valores
- Esta consulta compuesta devuelve un DataGraph con clases Dept y Emp de DataObject. La forma del DataGraph refleja las expresiones de vía de acceso utilizadas en las cláusulas FROM.
En este caso Dept es el nodo raíz del DataGraph y hay una referencia de varios valores de Dept a Emp como se muestra: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>
- Más sobre parámetros de consulta
- Las condiciones de búsqueda se pueden especificar en cualquier consulta. Los argumentos de entrada son globales a la consulta y se puede hacer referencia a éstos por número en cualquier parte de la consulta compuesta. En el ejemplo anterior, los argumentos de consulta pasados en la llamada a create o getGraph deben estar en orden {valor de deptno, valor de salary, valor de deptno}.
select d.* from Dept as d where d.deptno between ?1 and ?3 select e.* from in(d.emps) e where e.salary < ?2
- Navegación por vías de acceso con varias relaciones
- La consulta siguiente navega por la vía de acceso compuesta de relaciones de EJB Dept.projs y Project.tasks y devuelve DataObjects para Dept, Emp y Project que contienen los campos CMP seleccionados.
El gráfico de datos resultante en formato XML se muestra aquí.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>
- Navegación por varias vías de acceso
- A continuación figura una consulta del mediador que devuelve un DataGraph con DataObjects para Dept con empleados relacionados y una segunda vía de acceso que recupera proyectos y tareas relacionados.
El DataGraph devuelto se parece a éste: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>
- Navegación por relaciones de un solo valor
- Lo importante a señalar aquí es que aún cuando Emp sea el objeto de datos raíz del gráfico, varios objetos de datos Emp se relacionarán con el mismo objeto de datos Dept. Así que, a diferencia de los ejemplos anteriores, el gráfico de datos no tiene una forma de árbol cuando consulta las instancias del objeto de datos, existen varios objetos Emp raíz relacionados con el mismo objeto Dept. Pero después de todo es un gráfico de datos, no un árbol datos. Recuerde que las consultas del mediador permiten expresiones de vía de acceso de un solo valor en la cláusula FROM. Este es un cambio de la sintaxis de consulta de EJB estándar.
Y el DataGraph en formato XML se parece a esto: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>
- Expresiones de vía de acceso en la cláusula SELECT
- Esta consulta es similar a la anterior (las dos consultas devuelven datos del empleado junto con el número de departamento y el nombre) pero recuerde que el gráfico de datos contiene sólo un tipo de objeto de datos en esta consulta (frente a dos de la consulta anterior). Los campos deptno y el campo name son de sólo lectura porque provienen de una expresión de vía de acceso de la cláusula SELECT y no son campos CMP del 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
- Navegación por relaciones de muchos a muchos
- La relación de Emp a Task se considera una relación de muchos a muchos. La siguiente consulta recupera empleados, tareas y proyectos. Sólo se da una única aparición de cualquier tarea DataObject determinada en el DataGraph, incluso si se puede relacionar con muchos empleados.
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
- Varios enlaces entre objetos de datos
- El mediador de EJB le permite recuperar datos basados en relaciones y utilizar el mandato XREL para construir una o más relaciones adicionales basadas en datos ya recuperados. El mediador también permite la recuperación de datos basados en ASNname y la posterior construcción de una o más relaciones basadas en los datos recuperados utilizando el mandatoXREL. La siguiente consulta recupera departamentos, empleados que trabajan en los departamentos y empleados que gestionan los departamentos.
La segunda y tercera sentencias select devuelven instancias de DataObject Emp. Es posible que la misma instancia Emp se recupere a través de las relaciones d.emps y d.manager. El mediador de EJB crea una instancia Emp, pero crea ambas relaciones.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 siguiente consulta se procesa del siguiente modo. Los DataObjects Dept se crean a partir de los datos de la primera consulta. Los DataObjects Emp se crean a partir de los datos de la segunda consulta. A continuación, se crean las relaciones del gráfico para cualquier relación utilizada en la cláusula FROM o la palabra clave XREL. Durante la creación de relaciones, no se recuperan datos adicionales. En este ejemplo, un empleado que trabaja en un departamento denominado Dev aparece en el DataGraph. Si este empleado gestiona un departamento denominado Sales, la referencia manages está vacía. El departamento Dev se ha recuperado en la primera consulta, no así el departamento 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
Las relaciones emps y manager se construyen en función de las instancias de DataObject creadas a partir de las consultas. Un empleado cuyo nombre es "Dev", pero que trabaja en el departamento "Sales", tendrá una relación dept nula en el gráfico.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
El siguiente ejemplo muestra la recuperación de objetos de datos para todos los empleados, objetos y tareas de un determinado departamento y el enlace de los empleados con las tareas.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 una tarea se asigna a un empleado del departamento 42, ese enlace aparece en el gráfico de datos. Si la tarea se asigna a un empleado que no sea del departamento 42, el enlace no aparece en gráfico de datos porque la consulta ha filtrado el objeto de datos. Una palabra clave XREL puede ir seguida de una o más relaciones de EJB. Las relaciones bidireccionales pueden hacer referencia a cualquier nombre de rol. El origen y el destino de la relación deben recuperarse a partir de una o más consultas.
- Recuperación de objetos no relacionados
- La siguiente consulta recupera Dept y 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 siguiente consulta recupera Dept y Emps. Incluso si existen relaciones entre Dept y Emp (es decir, mgr y emps), no se utiliza ninguna en FROM o XREL de modo que el gráfico resultante no contiene los valores de relación.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%'
- Recuperación de relaciones nulas o vacías
- Esta consulta devuelve los departamentos sin empleados y los empleados sin departamento. Es probable que la aplicación desee asignar los empleados a uno de los departamentos. El objetivo de xrel es definir la relación e.dept (y el rol inverso d.emps) en el esquema de gráfico.
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
- Parámetro de entrada de tipo collection
- Se puede pasar una colección de enterprise beans como argumento de entrada al mediador de ejb y hacer referencia a éstos en la cláusula FROM. El uso de parámetros collection satisface el requisito de construir un gráfico de datos a partir de una colección de usuarios de enterprise beans ya activados.
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 consulta indicada itera por la colección de beans Dept y beans Emp relacionados aplicando los predicados de la consulta y construyendo el gráfico de datos. Los valores se obtendrán de los valores actuales de los beans. Ejemplo de un programa que utiliza un parámetro collection de ejb.// este método se ejecuta en un contexto de EJB y dentro de un ámbito de transacción 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); // proporciona a todos un aumento del 10% } // crear el parámetro collection de consulta Collection c = new LinkedList(); c.add(dept); Object[] parms = new Object[] { c}; // poner la colección de ejb en la matriz parms. // la colección que contiene el EJB dept se pasa al mediador de EJB 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; // el DataGraph contiene la información de sueldo actualizada y // todavía no comprometida. Los datos Dept y Emp se capturan mediante // instancias EJB activas en EJBContainer. // Los datos del proyecto se recuperan de la base de datos utilizando // relaciones gestionadas por contenedor. }
- Uso de MediatorAdapter
En este ejemplo, el adaptador procesa sucesos CREATE para objetos de datos EMP. Los atributos name (nombre) y salary (sueldo) se extraen del objeto de datos y se pasan al método create en el EmpLocalHome.
El método create devuelve una instancia del EJB Emp y el valor de clave primaria se copia de nuevo al DataObject. El llamante pueden obtener entonces el valor de clave generado. Después del proceso, el adaptador devuelve un valor de true. El adaptador ignora todos los demás cambios y los procesa el mediador de 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; // ejemplo de la clase Adapter que llama a un método create de EJB. 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() ); // establecer la clave primaria de SDO return true; } catch(Exception e){ // aquí va el código de manejo de errores } } 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) { // aquí va el código de manejo de errores } } public void end(){} }