1

その場でレポートを取得するために、かなり複雑な動的クエリ ビルダーを作成する必要があります。どのような種類のデータ構造が最適かについて、少し頭を悩ませています。

selectParts のリスト、fromParts のリスト、where 基準のリスト、order by、group by などを永続化のために保持するだけです。結合、特に外部結合、節を持つこと、および集約関数について考え始めると、少し曖昧になり始めます。

今のところ、最初にインターフェイスを構築し、できる限り先のことを考えようとしていますが、構造に制限があることが判明した場合は、一連のリファクタリングを行うことは間違いありません.

この質問をここに投稿しているのは、誰かが私たちが基にできる何かをすでに考え出していることを願っています. または、いくつかのライブラリなどを知っています。来週の実装に飛び込む前に、潜在的な問題についていくつかのヒントやヘッドアップを入手できれば幸いです.

4

2 に答える 2

2

私は過去に似たようなことを数回しました。いくつかの大きなことが頭に浮かびます..

  • where 句は、正しく理解するのが最も困難です。私が「式」と「述語」と呼ぶものに分ければ、簡単になります。
  • 式 - 列参照、パラメーター、リテラル、関数、集計 (カウント/合計)
  • 述語 - like、between、in、is null の比較 (述語には式が子として含まれます。たとえば、expr1 = expr2 です。次に、and/or/not などの複合語もあります。
  • ご想像のとおり、where 句全体は、ルートに述語があり、その下におそらくサブ述語があり、最終的に葉の式で終了するツリーです。
  • HQL を構築するには、モデルをウォークします (通常は最初に深さ)。他の理由でモデルをウォークする必要があるため、ビジターを使用しましたが、複数の目的がない場合は、レンダリング コードをモデルに直接組み込むことができます。

たとえば、あなたが持っていた場合

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

すると木は

根
- と
  - 同等
    - 機能(上)
      - 列参照 (列 1)
    - パラメータ(param1)
  - また
    - 無効です
      - 列参照 (列 2)
    - 間
      - 列参照 (列 3)
      - パラメータ(param2)
      - パラメータ(param3)

次に、最初にツリーの深さをたどり、途中でレンダリングされた HQL のビットをマージします。たとえば、上の関数は、子 HQL の 1 つの部分がレンダリングされることを期待し、それを生成します。

"upper( " + childHql + " )"

それを親に渡します。Between のようなものは、3 つの子 HQL ピースを想定しています。

  • その後、select/group by/order by 句で式モデルを再利用できます。

  • 必要に応じて、select を保存するだけでグループの保存をスキップし、集計のクエリ構築スキャンをスキップできます。1 つ以上ある場合は、すべての非集計選択式を group by にコピーします。

  • From 句は、テーブル参照 + ゼロ個以上の結合句の単なるリストです。各結合句には、タイプ (内部/左/右) とテーブル参照があります。テーブル参照は、テーブル名 + オプションのエイリアスです。

さらに、クエリ言語 (または実際には何か) を解析したい場合は、ANTLRを強くお勧めします。学習曲線はかなり急ですが、見るべき文法例がたくさんあります。

HTH。

于 2009-10-16T10:43:16.963 に答える
0

EJB-QL パーサーとデータ構造が必要な場合は、EclipseLink (いくつかの内部クラス) に適切なものがあります。

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

JPQLParseTreeすべてのデータが含まれています。

ただし、変更されたものから EJB-QL を生成JPQLParseTreeすることは、自分で行う必要があります。

于 2010-06-01T13:44:14.267 に答える