2009-10-16 3 views
1

즉시 보고서를 가져 오기 위해 상당히 복잡한 동적 쿼리 작성기를 생성해야합니다. 우리는 어떤 종류의 데이터 구조가 가장 좋을지에 대해 약간 머리를 찰.하고 있습니다.HQL 또는 EJB QL을 유지하기위한 데이터 구조

실제로는 selectParts 목록, fromParts 목록, 조건 기준, 정렬 기준, 그룹 기준, 지속성에 대한 목록 만 있으면됩니다. 조인, 특히 외부 조인, 절 및 집계 함수에 대해 생각하기 시작하면 상황이 다소 흐려지기 시작합니다.

우리는 지금 당장 인터페이스를 구축하고 우리가 할 수있는 한 멀리 생각하려고 노력하고 있지만, 구조에 대한 제한 사항을 발견 할 때 일련의 리펙토링을 확실히 통과 할 것입니다.

나는이 질문을 누군가가 이미 우리가 기반으로 할 수있는 것을 생각해 내길 바라고 게시하고 있습니다. 또는 일부 라이브러리 또는 일부를 알고 있습니다. 다음 주에 구현하기 전에 잠정적 인 문제에 대한 조언이나 조언을 얻는 것이 좋을 것입니다.

답변

2

나는 과거 몇 번 비슷한 비슷한 일을 해왔습니다. 더 큰 것들이 떠올랐다. ..

  • where 절은 올바르게 작동하기가 가장 어렵다. 당신이 "표현"과 "술어"라고 부르는 것으로 나누면 쉽게 만들어집니다.
  • 표현식 - 열 참조, 매개 변수, 리터럴, 함수, 집계
  • 조건부 -와 같은 비교는 null입니다 (술어는 표현식을 자식으로 사용합니다 (예 : expr1 = expr2).
  • 상상할 수있는 것처럼 전체 where 절은 루트에 술어가있는 트리이며 하위에 하위 술어가 있고 결국에는 잎에서 표현식으로 끝납니다.
  • HQL을 생성하기 위해서는 먼저 모델을 걸어야합니다. (보통 깊이를 우선적으로 사용합니다.) 다른 이유로 인해 모델을 걷기 위해 방문자를 사용했지만 여러 목적이 없으면 렌더링 코드를 모델에 바로 빌드 할 수 있습니다.

당신이

"where upper(column1) = :param1 AND (column2 is null OR column3 between :param2 and param3)" 

이 있다면 그런 나무는

 
Root 
- AND 
    - Equal 
    - Function(upper) 
     - ColumnReference(column1) 
    - Parameter(param1) 
    - OR 
    - IsNull 
     - ColumnReference(column2) 
    - Between 
     - ColumnReference(column3) 
     - Parameter(param2) 
     - Parameter(param3) 

는 그런 다음 백업 방법에 HQL의 렌더링 비트를 먼저 트리 깊이를 걸어 병합입니다. 예를 들어 상단 기능은 아이 HQL의 한 조각이 렌더링 기대하고 그 다음

"upper(" + childHql + ")"

를 생성하고 그 부모에 그를 통과 할 것입니다. Between과 같은 것은 세 개의 자식 HQL 조각을 기대합니다.

  • 그런 다음 절에서/명령에 의해 선택/그룹 식 모델을 다시 사용할 수 있습니다

  • 당신은 방금 저장하여 원하는 경우로 그룹을 저장 건너 뛸 수 있습니다

    선택 및 쿼리 건설 전 집계를 스캔하십시오. 하나 또는 그 이상이있는 경우 모든 비 집합 선택 식을에 의해 그룹에 복사하십시오.

  • From 절은 테이블 참조 + 0 개 이상의 조인 절의 목록입니다. 각 조인 절에는 유형 (내부/왼쪽/오른쪽)과 테이블 참조가 있습니다. 테이블 참조는 테이블 이름 + 선택적 별명입니다. 혹시 쿼리 언어 (또는 정말 아무것도) 구문 분석하고자 들어갈 경우

플러스, 나는 매우 ANTLR을 추천 할 수 있습니다. 학습 곡선은 꽤 가파르 긴하지만 볼만한 예제 문법이 많이 있습니다.

HTH.

+0

감사합니다. 그것은 확실히 도움이됩니다. – aberrant80

0

당신은 EJB-QL 파서 및 데이터 구조가 필요한 경우는 EclipseLink (그 아니라 여러 내부 클래스의)는 좋은 일이 :

JPQLParseTree tree = org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.buildParserFor(" _the_ejb_ql_string_ ").parse(); 

JPQLParseTree는 모든 데이터가 포함되어 있습니다.

수정 된 JPQLParseTree에서 EJB-QL을 생성하면 스스로해야합니다.