테이블 조인을 포함하는 SQL 쿼리의 중첩된 Bean 개발

중첩된 Bean의 세트에 있는 pureQuery 어노테이션을 사용하여 테이블 조인을 포함하는 SQL 쿼리에서 데이터를 리턴하는 Bean의 세트를 작성합니다. pureQuery Runtime은 중첩된 Bean 세트의 구현을 생성합니다. 구현은 Bean에 추가된 pureQuery 어노테이션 및 SQL문의 테이블 조인을 기반으로 합니다.

리턴하려는 데이터의 계층 데이터 구조를 정의하는 중첩된 Bean 세트를 작성합니다. @JoinPoint 어노테이션을 ResultSet 오브젝트의 열과 일치하는 Bean 특성에 지정하는 경우 pureQuery Runtime이 적절한 구현을 생성합니다. pureQuery Runtime은 ResultSet 오브젝트 및 중첩된 Bean 처리 후에 리턴되는 Bean인 최상위 레벨 Bean의 계층 구조를 분석합니다. ResultSet 오브젝트 열에 의해 업데이트되고 @JoinPoint 어노테이션이 있는 Bean 또는 Bean 목록만 생성되고 채워집니다. ResultSet 오브젝트 열에 의해 채워지지 않고 @JoinPoint 어노테이션이 없는 Bean 또는 Bean 목록은 널(NULL) 또는 Bean 생성자 초기화 값입니다.

중첩된 Bean 세트에 대한 예

다음은 두 Bean을 표시하는 예입니다. 최상위 레벨 Bean은 부서 bean이며 하위 bean은 직원 bean의 목록입니다.

예에서는 DEPARTMENT와 EMPLOYEE 테이블 간 결합과 함께 다음 SQL 쿼리를 사용합니다. 쿼리는 하나의 매개변수, 부서 번호를 취하고 부서에 속하는 모든 직원을 리턴합니다.
Select D.DEPTNO, D.DEPTNAME, D.MGRNO, D.ADMRDEPT, E.EMPNO, E.FIRSTNME, E.MIDINIT, 
     E.LASTNAME, E.JOB, E.SEX, E.BIRTHDATE, E.SALARY 
   from (DEPARTMENT AS D LEFT JOIN EMPLOYEE AS E ON D.DEPTNO=E.WORKDEPT) 
   WHERE D.DEPTNO=? ORDER BY D.DEPTNO, E.LASTNAME
다음 DAO 인터페이스 메소드는 SQL 쿼리를 지정합니다.
  @Select(sql = "Select D.DEPTNO, D.DEPTNAME, D.MGRNO, D.ADMRDEPT, E.EMPNO, 
     E.FIRSTNME, E.MIDINIT, E.LASTNAME, E.JOB, E.SEX, E.BIRTHDATE, E.SALARY 
    from (DEPARTMENT AS D LEFT JOIN EMPLOYEE AS E ON D.DEPTNO=E.WORKDEPT) 
    WHERE D.DEPTNO=? ORDER BY D.DEPTNO, E.LASTNAME")
  public Department joinTest (String deptNo);

다음 두 Bean은 SQL 쿼리를 위해 개발되었습니다. 부서 Bean은 결과 세트 처리 후에 리턴되는 최상위 레벨 Bean입니다. 부서 Bean은 deptEmployees Bean 목록의 상위 Bean입니다. deptEmployees Bean의 목록은 하위 Bean 세트입니다. @Id 어노테이션이 있는 Bean의 특성인 ID 컬럼은 deptNo입니다.
@Table(name = "DEPARTMENT")
public class Department
{
  @Id
  @GeneratedKey
  public String deptNo; // this is the ID of the bean and its value is generated by the database
  public String deptName;
  public String mgrNo;
  public String admrDept;
  @JoinPoint(@JoinColumn(name = "EMPNO", table = "EMPLOYEE", propertyName = "empNo"))
  public List<Employee> deptEmployees;
} 
deptEmployees Bean 목록이 리턴한 데이터는 Employee 클래스가 정의합니다.
@Table(name = "EMPLOYEE")
public class Employee
{
  @Id
  @GeneratedKey
  public String empNo; // this is the ID of the bean and its value is generated by the database
  public String firstNme;
  public String midInit;
  public String lastName;
  public String workDept;
  public String job;
  public String sex;
  public java.sql.Date birthdate;
  public String salary;
}

SQL 쿼리 및 Bean을 기반으로 pureQuery Runtime이 Bean의 구현 코드를 생성합니다.

리턴된 Java 오브젝트는 11개의 deptEmployees Bean의 java.util.list를 포함하는 하나의 부서 Bean입니다.

joinTest("D11") 메소드 호출로 결과가 형식화되어 출력됩니다. 처음 네 개의 열은 부서 Bean의 데이터이며 직원 데이터의 기타 열은 deptEmployees Bean의 데이터입니다.
dept                             admr                    mid
No  deptName              mgrNo  Dept empNo    firstNme  Init lastName  job      sex birthdate  salary
D11 MANUFACTURING SYSTEMS 000060 D01  000150   BRUCE          ADAMSON   DESIGNER M   1977-05-17 55280.00
                                      000200   DAVID          BROWN     DESIGNER M   1971-05-29 57740.00
                                      200220   REBA      K    JOHN      DESIGNER F   1978-03-19 69840.00
                                      000210   WILLIAM   T    JONES     DESIGNER M   2003-02-23 68270.00
                                      000220   JENNIFER  K    LUTZ      DESIGNER F   1978-03-19 49840.00
                                      000160   ELIZABETH R    PIANKA    DESIGNER F   1980-04-12 62250.00
                                      000180   MARILYN   S    SCOUTTEN  DESIGNER F   1979-02-21 51340.00
                                      000060   IRVING    F    STERN     MANAGER  M   1975-07-07 72250.00
                                      000190   JAMES     H    WALKER    DESIGNER M   1982-06-25 50450.00
                                      200170   KIYOSHI        YAMAMOTO  DESIGNER M   1981-01-05 64680.00
                                      000170   MASATOSHI J    YOSHIMURA DESIGNER M   1981-01-05 44680.00 

중첩된 Bean 세트에서 Bean의 유형

테이블 조인을 포함하는 SQL 쿼리에 대한 중첩된 Bean 세트를 작성할 때 해당 유형의 Bean을 작성합니다.
최상위 레벨 Bean
최상위 레벨 Bean은 인라인 API 또는 메소드의 리턴값인 Bean입니다. 중첩된 Bean 세트의 pureQuery 어노테이션과 함께 사용되는 경우 최상위 레벨 Bean에 하나 이상의 @Id 어노테이션이 있어야 합니다. 상위 Bean으로써 여기에는 하나 이상의 @JoinPoint 어노테이션도 포함되어 있어야 합니다. Bean은 상위 또는 하위 Bean일 수 있습니다. 경우에 따라서 Bean은 동일한 중첩 구조에서 상위 및 하위 Bean 모두일 수 있습니다.
상위 Bean
상위 Bean은 Bean 또는 Bean 목록, 하위 Bean을 참조하는 최소 하나의 @JoinPoint 어노테이션을 포함해야 합니다. 최상위 레벨 Bean이 아닌 한 상위 Bean에서 @Id 어노테이션이 필요하지 않습니다. 상위 Bean(예: BeanB)에 @Id 어노테이션이 포함되어 있지 않은 경우에도 하위 Bean이어야 합니다. BeanB, BeanA의 상위 Bean과 여기에는 @JoinPoint 어노테이션의 @JoinColumn 어노테이션이 포함되어야 합니다. BeanA의 @JoinColumn 어노테이션이 하위 Bean(BeanB)의 ID 컬럼을 지정합니다.
하위 Bean
하위 Bean은 @JoinPoint 어노테이션이 있는 해당 상위 Bean이 참조합니다. 최상위 레벨 Bean이기도 하지 않은 한 하위 Bean은 @Id 어노테이션을 포함할 필요가 없습니다. 하위 Bean이 @Id 어노테이션을 포함하지 않는 경우 해당 상위 Bean은 @JoinPoint 어노테이션 내에 있는 하나 이상의 @JoinColumn 어노테이션과 함께 이 Bean의 ID 컬럼을 지정해야 합니다.

중첩된 Bean 세트의 ID 컬럼

중첩된 Bean 세트를 생성하고 채울 때 pureQuery Runtime은 Bean 상위에 있는 Bean에 대한 참조의 @JoinPoint 어노테이션 또는 Bean 자체의 @Id 어노테이션을 사용합니다. 어노테이션은 상위 Bean에 하위 Bean을 링크하는 ID 컬럼을 정의합니다. 예를 들어, pureQuery Runtime은 ID 컬럼을 사용하여 상위 Bean의 Bean 목록을 생성할 시기를 판별합니다.

예를 들어, EMPLOYEE 테이블은 열을 식별할 수 있는 복수 컬럼을 포함할 수 있습니다. ID 컬럼으로 정의될 수 있는 열은 직원 번호 또는 직원 주민등록번호입니다. ID 컬럼은 테이블의 기본 키일 수 있지만 테이블 키일 필요는 없습니다. 복합 키가 데이터베이스 테이블에서 작성될 수 있는 것처럼 복수 컬럼은 복합 키로 결합될 수 있습니다. 동일한 이름을 가진 직원이 있을 수 있으므로 EMPLOYEE 테이블 ID 컬럼에 이름을 선택하는 것은 좋지 않습니다.

pureQuery Runtime은 ResultSet 오브젝트를 처리할 때 기타 Bean 정보 및 ID 컬럼 정보를 사용합니다. 테이블 조인을 포함하는 SQL 쿼리의 경우 ResultSet 오브젝트의 데이터가 Bean의 계층 구조로 데이터를 맵핑하는 것을 어렵게 만들 수도 있습니다. 다음은 처리 중에 문제점을 발생시킬 수 있는 일부 특성입니다.
  • 데이터 순서가 정렬되지 않았을 수 있습니다.
  • 데이터베이스 테이블의 데이터 순서를 유지해야할 수도 있습니다.
  • ResultSet의 데이터가 중복됩니다. 이는 데이터가 데이터베이스에서 일대다 관계를 포함할 때 발생합니다. 예를 들어, 하나의 부서에 다수의 직원이 있습니다. ResultSet는 부서 테이블과 직원 테이블 간 결합의 데이터를 포함할 수 있습니다. 부서의 각 직원에 대한 부서 정보가 중복됩니다.

pureQuery Runtime은 Bean이 올바른 순서의 올바른 데이터 세트로 채워지는지 확인합니다. 예를 들어, ResultSet 데이터는 중첩된 Bean 구조로 정확히 맵핑되도록 정렬되지 않을 수 있습니다. pureQuery Runtime은 ResultSet의 처리 이전에 작성된 Bean에 속하는 ResultSet 데이터를 프로세스할 수 있으며 올바른 순서의 적절한 데이터로 Bean을 채울 수 있습니다.

중첩된 Bean 세트 작성 규칙

적절한 어노테이션과 함께 더 복잡한 중첩 구조를 작성하여 복합 Join 술어가 있는 SQL문에서 결과를 리턴하는 중첩된 Bean 세트를 작성할 수 있습니다. 올바른 결과를 리턴하는 중첩된 Bean 세트를 작성하려면 다음 규칙을 따라야 합니다. SQL 쿼리 또는 Bean에 대한 변경사항은 유용한 Bean 세트를 생성하는 데 필요할 수 있습니다.

  1. ResultSet 오브젝트에 있는 각 열의 컬럼 이름을 상위 Bean 또는 하위 Bean의 단일 특성에 맵핑해야 합니다.
    주: 둘 이상의 열을 제공된 특성에 맵핑하고 열이 항상 동일한 데이터를 리턴하는 경우 이 맵핑은 문제되지 않습니다. 하나 이상의 열이 널(NULL)일 수 있는 경우 문제점이 발생할 수 있습니다. 예를 들어, 열은 테이블 조인을 포함하는 SQL 쿼리에서 널(NULL)을 리턴할 수 있습니다. 쿼리는 두 테이블 간에 일치하는 키를 찾지 않는 WHERE 또는 ON절을 포함할 수 있습니다.

    이 문제점은 SQL 쿼리에서 별명을 지정하여 해결할 수 있습니다. @Column, @Table 또는 @JoinColumn 어노테이션은 둘 이상의 열이 있는 Bean의 특성의 테이블 이름과 함께 지정될 수도 있습니다.

  2. 중첩된 Bean 구조에 동일한 Bean이 여러 번 포함되는 경우 첫 번째 인스턴스 후 해당 Bean에 대한 모든 참조가 무시됩니다. 첫 번째 인스턴스만 사용하면 pureQuery Runtime이 중첩된 Bean 세트를 처리할 때 무한 반복 가능성을 예방합니다. @JoinPoint 선택적 요소 columnPrefix 또는 SQL 쿼리의 원래 Bean 및 열 별명의 서브클래스 또는 @JoinPoint 또는 @JoinColumn 어노테이션을 사용하여 다수의 유사한 Bean을 작성하십시오.
  3. @JoinColumn 필수 요소 name이 하위 Bean의 기본 특성 이름과 일치해야 합니다. 일치하지 않는 경우 선택적 요소 propertyName은 하위 Bean에 있는 일치하는 기본 특성의 이름과 함께 지정되어야 합니다.

    기본 특성 이름은 ResultSet 오브젝트에 대한 해당 맵핑을 수정하는 기존 어노테이션이 없는 Bean 특성의 이름입니다. 필드의 경우 기본 특성 이름은 Java 변수 이름입니다. 가져오기, 세트 또는 is 메소드의 경우 이는 get, set 또는 is 접두부가 없고 첫 번째 문자가 소문자인 메소드 이름입니다. 다음 예에서 ResultSet 열 레이블 WORKDEPT는 대소문자를 구분하지 않습니다.

    다음 예 가져오기 메소드에서 기본 특성 이름 workDepartment은 대소문자를 구분합니다.
    @Column (name = "WORKDEPT")
    public String getWorkDepartment (); 

    @JoinColumn 어노테이션은 Bean 또는 Bean 목록의 @JoinPoint 어노테이션 내에 지정할 수 있습니다. 그런 경우 지정된 nametable 요소는 지정되는 연관된 @Column 어노테이션을 포함하여, 하위 Bean @Id 어노테이션에서 정의되는 열 레이블 및 선택적 테이블 이름을 겹쳐씁니다.

    하위 Bean은 @Id 어노테이션을 가질 수 있습니다. 이 경우 @JoinColumn 어노테이션 필수 요소 name은 하위 Bean의 기본 특성 이름과 일치해야 합니다. 이름이 일치하지 않는 경우 선택적 요소 propertyName은 하위 Bean에 있는 일치하는 기본 특성의 이름과 함께 지정되어야 합니다.

    SQL 쿼리에 있는 EMPNO의 별명이 EMPNUM이 되도록 이전 예를 수정하는 경우 propertyName 요소는 @JoinColumn 어노테이션에 필요하지 않습니다. 하위 Bean에는 하나의 @Id 어노테이션이 있으며 pureQuery Runtime은 맵핑할 특성을 판별합니다. 다음 부서 Bean @JoinPoint 어노테이션이 수정할 수 있습니다.
    @JoinPoint(@JoinColumn(name = "EMPNO", table = "EMPLOYEE", propertyName = "empNo"))
      public List<Employee> deptEmployees;
    @JoinPoint 어노테이션을 다음과 같이 지정할 수 있습니다.
      @JoinPoint(@JoinColumn(name = "EMPNUM", table = "EMPLOYEE", propertyName = "empNo"))
       public List<Employee> deptEmployees;
    직원 하위 Bean의 ID 컬럼을 empNo에서 workDept로 변경하려는 경우 다음과 같이 PropertyName 요소를 지정하십시오.
      @JoinPoint(@JoinColumn(name = "WORKDEPT", table = "EMPLOYEE", propertyName = "workDept"))
      public List<Employee> deptEmployees;
  4. @Table 어노테이션은 클래스 레벨에서 사용됩니다. 어노테이션은 테이블 이름을 지정하지 않는 모든 특성에 추가될 기본 테이블 이름을 지정합니다. 테이블 이름과 일치하는 특성을 지정하도록 테이블 이름을 겹쳐쓸 수 있습니다.
  5. 하위 Bean에는 중첩된 Bean 세트의 파트로 고려될 @Id 어노테이션이 필요하지 않습니다. @JoinPoint 어노테이션은 하위 Bean의 ID 컬럼을 지정할 수 있습니다. @Id 어노테이션이 있는 ID 컬럼의 이 스펙은 해당 호출의 해당 상위 Bean 전용입니다.

    하위 Bean은 단일 Bean이거나 Bean의 목록이어야 하며 하위 Bean에는 @JoinPoint 어노테이션이 있어야 합니다. 하위 Bean 또는 Bean 목록을 정의하는 상위 Bean 특성에 @JoinPoint 어노테이션이 있어야 합니다.

  6. ResultSet 오브젝트의 각 열을 올바른 상위 Bean 및 하위 Bean의 특성에만 맵핑해야 합니다.

    이 맵핑의 예는 기본 키인 열 DEPTNO가 있는 DEPARTMENT 테이블 및 열 DEPTNO가 있는 PROJECT 테이블입니다. PROJECT 테이블 DEPTNO 열은 DEPARTMENT 테이블의 외부 키입니다. ResultSet 오브젝트의 열 및 특성 간의 기본 일치는 열 레이블입니다. 이 예에서 DEPARTMENT 및 PROJECT 테이블의 결합으로 열 레이블이 DEPTNO인 두 열이 생길 수 있습니다. 상위 및 하위 Bean 구조에 다른 정보가 있는 열이 필요한 경우 Bean에 어노테이션을 추가할 수 있습니다. 어노테이션은 테이블 이름을 사용하여 열을 고유하게 만들 수 있습니다. 또한 고유한 열 레이블을 작성하기 위해 별명을 추가하여 SQL문을 수정할 수도 있습니다. 그러나 이는 다중 열에 동일한 데이터가 포함될 때 하나의 열만 리턴하는 결합에 대한 SQL 조회에서 공통적입니다. 이 경우 이는 다중 특성을 업데이트하기 위한 하나의 열에만 유효합니다.

    데이터 액세스 오브젝트(DAO) 스타일 메소드를 사용하면 다음 방법으로 ResultSet 오브젝트에서 동일한 열에 의해 업데이트될 다중 특성의 경고가 표시됩니다.
    • 경고가 생성되며 동일한 열을 사용하는 생성 메소드에 대해 설명합니다. IBM® Data Studio를 사용하는 경우 구현 생성 후에 이 경고가 표시됩니다. 경고가 있고 추적 레벨이 java.util.logging.Level.WARNING 또는 자세히로 설정되는 경우 생성 프로그램 로그 파일에 경고가 포함됩니다.
    • pureQuery 생성 프로그램은 생성된 중첩 ResultHandler 위에 주석 블록을 작성합니다. 주석에는 ResultSet 열을 사용하는 생성 핸들러가 표시됩니다. 여기에는 또한 절대 사용되지 않는 ResultSet 열도 표시됩니다.

    인라인 메소드 스타일을 사용하면 동일한 ResultSet 열에 의해 업데이트될 다중 특성의 경고가 표시됩니다. 경고가 있고 추적 레벨이 java.util.logging.Level.WARNING 또는 자세히로 설정되는 경우 pureQuery Runtime 로그 파일에 경고가 로그인됩니다.

  7. @JoinPoint 어노테이션은 하위 Bean이 상위 Bean에 결합될 때마다 필요합니다. 다음 명령문이 참일 때를 제외하고 하나의 @JoinColumn 어노테이션이 @JoinPoint 어노테이션 내에 지정되어야 합니다.
    • 하위 Bean 또는 Bean 목록은 하위 Bean의 ID 컬럼을 완전히 정의하는 하나 이상의 @Id 어노테이션을 포함합니다.
    • 선택적 열 레이블 및 테이블 이름이 있는 하위 Bean ID 컬럼 특성은 ResultSet 오브젝트 작성을 위해 실행되는 SQL문의 열을 올바르게 지정합니다. 이 경우 요소 없이 @JoinPoint 어노테이션만 지정할 수 있습니다.

중첩된 Bean 런타임 처리

이 단계에서는 ResultSet 오브젝트의 데이터로 오브젝트를 생성할 때 pureQuery Runtime이 중첩된 Bean 세트를 프로세스하는 방법을 설명합니다.
  1. 구문 분석은 리턴되는 Bean(최상위 레벨 상위 Bean)으로 시작합니다. Bean의 각 특성은 ResultSet 오브젝트가 특성을 업데이트하는지 여부를 판별하기 위해 검사됩니다. 특성이 업데이트되고 @JoinPoint 어노테이션이 있는 경우 특성은 Bean 또는 Bean 목록을 참조하는지 여부를 판별하기 위해 검사됩니다. 특성이 Bean 또는 Bean 목록을 참조하는 경우 Bean은 상위 Bean의 하위 Bean 목록에 추가됩니다. pureQuery Runtime이 찾은 모든 하위 Bean을 프로세스하기 전에 상위 Bean의 모든 특성이 프로세스됩니다. 특성이 Bean 내에서 검사되는 순서는 결정적이지 않습니다.
  2. 상위 Bean에 있는 모든 특성이 검사된 후 하위 Bean의 목록이 검사됩니다. 목록이 하나 이상의 하위 Bean을 포함하는 경우 목록의 첫 번째 Bean은 상위 Bean처럼 프로세스됩니다.
  3. 원래 상위 Bean에서 첫 번째 하위 Bean을 찾고 해다 하위 Bean의 목록이 작성된 후 pureQuery Runtime이 원래 상위 Bean의 다음 하위 Bean을 프로세스합니다. 다른 Bean이 있는 경우 이전 단계에서와 같이 프로세스됩니다.

    원래 상위 Bean의 모든 하위 Bean은 하위 Bean이 있는지 여부를 판별하도록 하위 Bean이 프로세스되기 전에 프로세스됩니다.

pureQuery Runtime은 하위 Bean 클래스가 처음으로 프로세스되는지 여부 또는 Bean에 반복적 참조가 있는지 여부를 판별할 수 있습니다. 중첩된 Bean 구조를 구문 분석하는 pureQuery Runtime에서 이미 구문 분석된 Bean을 발견하는 경우 해당 하위 Bean의 구문 분석이 중지됩니다.

주: 둘 이상의 동일한 하위 Bean을 포함하는 상위 Bean을 가지는 것은 지원되지 않습니다. 이런 상황에서 pureQuery Runtime은 정보를 하나의 하위 Bean에만 포함합니다. 하위 Bean의 고유 특성 어노테이션으로 서브클래스를 지정할 수 있습니다. 또한 각 중복 클래스의 상위 Bean @JoinPoint 어노테이션에 있는 columnPrefix 요소를 사용할 수도 있습니다.

Bean에 대한 반복적 참조도 pureQuery runtime이 하위 Bean의 특성을 채우는 방법에 영향을 미칩니다. Bean의 첫 번째 인스턴스만 채워집니다. 참조에 정의된 다른 columnPrefix 요소가 있는 @JoinColumn 어노테이션이 있지 않는 한 해당 참조에 대한 이후 참조가 무시됩니다. 단일 Bean 내의 특성 처리 순서가 비결정적이므로 하위 Bean이 프로세스되는 순서도 비결정적입니다. 그러나 하위 Bean은 중첩 레벨 순서로 프로세스됩니다. 예를 들어, 상위 Bean에서 직접 중첩되는 Bean은 다음 중첩 레벨의 Bean 이전에 프로세스됩니다.

columnPrefix 요소에 대한 정보는 @JoinPoint 어노테이션 문서를 참조하십시오.


피드백