데이터 액세스를 위한 EJB 데이터 중개자 서비스 사용
다음 단계는 코드 샘플을 사용하여 EJB(Enterprise JavaBeans) 데이터 중개자 서비스(DMS) 메타데이터를 작성하는 방법의 간단한 인스턴스에 대해 설명합니다.
프로시저
예
- EJB 중개자에서 조회 인수 사용
다음 예는 EJB(Enterprise JavaBeans) 중개자 조회 인수를 미세하게 조정하는 방법을 보여줍니다.
- 간단한 예
- 이 조회는 유형(Eclass 이름) Emp의 DataObject의 다중 인스턴스가 포함된 DataGraph를 리턴합니다. 데이터 오브젝트 속성은 empid 및 name이며 해당 데이터 유형은 CMP(Container-Managed Persistence) 필드 유형과 대응됩니다.
자체 XML 형식으로 직렬화된 리턴된 DataGraph는 다음과 유사합니다.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>
- 조회 매개변수
- 이 예에서는 매개변수 마커를 사용하는 방법을 표시합니다. 참고로, EJB 조회에서 매개변수 마커의 구문은 물음표 다음에 숫자(?n)인 것을 다시 호출합니다. EJBMediator에서 getGraph( ) 메소드를 호출하는 경우에는 선택적으로 값의 배열을 전달할 수 있습니다. ?n은 parm[n-1]의 값을 참조합니다. 값의 배열이 EJBMediator를 작성하기 위해 팩토리 호출에서 전달될 수도 있습니다. getGraph( )에서 전달된 매개변수는 작성 호출에서 전달된 모든 매개변수를 대체합니다.
select e.empid, e.name from Emp as e where e.salary > ?1
- 표현식 및 메소드 리턴
- 이 예에서는 데이터 오브젝트 속성이 조회 표현식의 리턴값일 수 있음을 예시합니다. EJB 조회 표현식에는 산술, 날짜-시간, 경로 표현식 및 메소드가 포함됩니다. 메소드의 리턴값 및 입력 인수는 지원되는 데이터 유형의 목록으로 제한됩니다. EJB 중개자 조회 구문 주제를 참조하십시오. 사용자가 변경사항 처리를 위해 MediatorAdapter를 제공하지 않았으면, 표현식에서 유도된 업데이트된 속성을 포함하는 데이터 오브젝트는 applyChanges 프로세스 중에 예외가 발생하도록 합니다.
데이터 오브젝트 속성 이름은 CMP 필드 이름에서 파생되지만, 조회에서 AS 키워드를 사용하여 대체될 수 있습니다. 표현식을 지정할 때 AS 키워드는 항상 표현식에 이름을 부여하기 위해 사용되어야 합니다.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
- * 구문
- e.* 표기는 EJB에 대해 모든 CMP 필드(컨테이너 관리 관계는 아님)를 지정하기 위한 단축키입니다. 다음 조회는 e.empid, e.name e.salary, e.bonus와 동일한 의미를 지닙니다.
select e.* from Emp as e
- select 절에 기본 키가 없음
- 이 예는 기본 키 필드를 리턴하지 않는 조회를 보여줍니다. 그러나 데이터 오브젝트에 EJB에 대한 모든 기본 키 필드가 포함되지 않으면, DataGraph에 대한 업데이트를 중개자가 처리할 수 없습니다. 이는 기본 키가 변경사항을 SQL(Structured Query Language)로 변환하거나 DataObject 참조를 EJB 참조로 변환해야 하기 때문입니다. applyChanges가 실행할 때의 예외입니다.
select e.name, e.salary from Emp as e
- 정렬 기준
- DataObjects를 정렬할 수 있습니다.
결과적으로 Dept 오브젝트는 이름순으로 정렬되며 각 Dept 내의 Emp 오브젝트는 내림차순으로 empid에 의해 정렬됩니다.select d.* from Dept d order by d.name select e.* from in(d.emps) e order by e.empid desc
- 다중 값 관계 탐색
- 이 복합 조회는 데이터 오브젝트 클래스 Dept 및 Emp의 DataGraph를 리턴합니다. DataGraph의 형태는 FROM 절에서 사용되는 경로 표현식을 반영합니다.
이 경우에 Dept는 DataGraph의 루트 노드이며, 표시된 대로 Dept에서 Emp로의 다중 값 참조가 있습니다.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>
- 조회 매개변수의 추가 정보
- 검색 조건은 임의의 조회에서 지정될 수 있습니다. 입력 인수는 조회에 대해 글로벌이며 복합 조회의 어디에서든 번호에 의해 참조될 수 있습니다. 이전 예에서, 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에 대한 데이터 오브젝트를 리턴합니다.
XML 형식의 결과 데이터 그래프가 다음에 표시되어 있습니다.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>
- 다중 경로 탐색
- 다음은 관련 사원의 Dept에 대한 DataObjects의 DataGraph와 관련 프로젝트 및 태스크를 검색하는 두 번째 경로를 리턴하는 중개자 조회입니다.
리턴된 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
<?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 데이터 오브젝트와 관련된다는 것입니다. 따라서 이전 예와는 달리 데이터 오브젝트 인스턴스를 조사할 때 데이터 그래프가 트리 모양을 갖지 않으며 동일한 Dept 오브젝트와 관련된 복수의 루트 Emp 오브젝트가 있습니다. 그러나 결국에는 데이터 트리가 아니라 데이터 그래프입니다. 참고로, 중개자 조회는 FROM 절에서 단일 값 경로 표현식을 허용합니다. 이것이 표준 EJB 조회 구문으로부터 변경된 사항입니다.
또한 XML 형식의 DataGraph는 다음과 같습니다.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>
- SELECT 절의 경로 표현식
- 이 조회는 이전 조회와 유사하지만(두 조회 모두 부서 번호 및 이름과 함께 사원 데이터를 리턴함), 데이터 그래프에는 이 조회의 한 데이터 오브젝트 유형만(이전 조회의 두 유형과 대조적으로) 포함된다는 사실을 참고하십시오. 필드 deptno 및 이름 필드는 읽기 전용입니다. 왜냐하면 이 필드가 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 대 태스크 관계는 다대다 관계로 간주됩니다. 다음 조회는 직원, 태스크 및 프로젝트를 검색합니다. 많은 직원과 관련될 수 있더라도 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 절은 둘 다 Emp DataObject 인스턴스를 리턴합니다. 동일한 Emp 인스턴스가 d.emps 관계 및 d.manager 관계를 통해 검색될 수 있습니다. EJB 중개자는 한 개의 Emp 인스턴스를 작성하지만 두 관계를 작성합니다.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
다음 조회는 다음과 같이 처리됩니다. Dept DataObjects는 첫 번째 조회의 데이터에서 작성됩니다. Emp DataObjects는 두 번째 조회의 데이터에서 작성됩니다. 그런 후 그래프의 관계가 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 관계는 조회에서 작성된 데이터 오브젝트 인스턴스에 기초하여 구성됩니다. 이름이 "Dev"이지만 "Sales" 부서에서 근무하는 직원은 그래프에서 널인 부서 관계를 갖습니다.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 및 Emps를 검색합니다. 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%'
- 널 또는 비어 있는 관계 검색
- 이 조회는 직원이 없는 부서와 부서가 없는 직원을 리턴합니다. 아마도 애플리케이션은 해당 직원을 부서 중 하나에 지정하고자 할 수 있습니다. 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(){} }