質問

JTableを使用して&を表示するにはどうすればよいですか?エンティティ、属性、値(EAV)ストア(リレーショナルDBMS)から取得したエンティティの属性プロパティを編集しますか?

これは可能な答えがたくさんある質問であることがわかっているので、答える前に以下の要件を確認してください。

あなたが読んだことを示す答えに投票することを約束します&全体を理解する(それらが完全に愚かでない限り)。


ユーザーは次のことができる必要があります:

  1. 属性によるエンティティのフィルタリング/検索

  2. (列として)表示する属性を選択します

  3. 選択した属性でエンティティをソート

  4. 属性値の編集

  5. 選択したエンティティに対して操作を行う

  6. (オプション)後で使用するためにビューを保存する機能。


システム要件:

  1. エンティティの数:10万以上の一意のエンティティにスケールアップする必要があります

  2. 属性:ユーザーは新しい属性を追加および定義できます。システムはこれを処理できる必要があります

  3. 基盤となるストレージ:H2データベース(既に設計されています)、JDBCによる通信

  4. メモリ:すべてが適合するわけではないため、何らかの理由でDBMSクエリからプルする必要があります

  5. パフォーマンス:DBMSに必要なクエリの数を最小限に抑える必要があります(属性ごとに1つのクエリで問題ありません。テーブルビューごとに1つのクエリがあるフォームがありますが、それは面倒です)。

  6. クエリ:検索/フィルターに一致するエンティティのリストを生成するには、1つのクエリが必要です。それ以外の場合、パフォーマンスが大幅に低下します。

  7. データの再利用:列が追加されたときにリスト全体を再クエリまたは再ソートする必要はありません。


見たもの:

  1. Glazed Listsライブラリ

    • 長所:

      • 列の処理について柔軟な
      • エンティティのソート/フィルターを簡単に実装
      • 列の表示形式について柔軟な&編集
    • 短所:

      • エンティティごとに1つのオブジェクト(オブジェクトが複雑な場合、メモリのオーバーヘッドが深刻なメモリの問題になります!)
      • すべての機能を担当するオブジェクト...ただし、オブジェクトはメモリ上の理由から単純でなければなりません
      • すべてのエンティティオブジェクトに対してHashMapなしでユーザーが選択可能な列をサポートするにはどうすればよいですか
  2. JDBC ResultSetのデータを行、列にマッピングするためのAbstractTableModelの拡張

    • 長所:
      • 結果のページングによりメモリの問題を回避
      • 検索/フィルタリングは直接SQLで行われます
      • メモリに優しい、行ごとにオブジェクトを作成する必要はありません
    • 短所:
      • カスタム列の実装&ソートは苦痛です(テーブルヘッダーレンダラー、ソート列と順序の管理など)。
      • おそらくカスタムJTableColumnModelも作成する必要があり、これは面倒になります!
      • SQLを多く操作する必要があるため、DBスキーマが変更された場合、複数のコードを書き直す必要があります!
      • エンティティID情報を維持するのが難しい
  3. ORM

    • 長所:
      • DB行をオブジェクトにマッピングするように設計されています
      • オブジェクト管理を提供します
    • 短所:
      • エンティティ属性値モデルの最悪の解決策
      • 学ぶ必要がある& DBMS&に加えてORMコードを記述しますJavaコード!
      • エンティティは any 個の属性を持つことができます。ORMは静的で制限されたオブジェクト属性でのみ有効です
      • カスタムSQLの柔軟性と速度の低下

見逃したより良いオプションや、グレーズリストやカスタムテーブルモデルを簡単にする賢い方法はありますか

ORVがEAVストレージに対してどれほどひどく一致するかという理由で、私はすでにオプションとしてORMを完全に破棄しました。

役に立ちましたか?

解決

最良のオプションは、「JDBC ResultSetからのフォームマップデータを使用してAbstractTableModelを拡張する」ことです。

  • Java 6 JTableにはソートサポートが組み込まれているため、実際に実装する必要はありません。
  • モデルを慎重に設計すると、スキーマの変更に耐えることができます。必要に応じて変更を簡単に行えるように、明確にコーディングしてください。
  • とにかく変更を書き戻す必要があります。 [保存]ボタンを使用すると、バッチ更新でパフォーマンスが向上する場合があります。
  • TableCellEditorをオーバーライドして、デフォルトのテキストエディターの代わりにコンボボックスを提供できます。
  • 1つのテーブルですべての編集を試みないでください。エントリ作成などの手段を分離しました。
  • 実行時にJTableに列を追加/削除できます。 fireTableModelChanged()だけで、新しい列が表示されます

編集:カスタムコンポーネントを作成し、すべてのレンダリングを自分で行い、適切に配置されたJTextFieldとJComboBoxを使用して編集操作を実行するために行う1つのクレイジーなこと。

Edit2:コメントに基づきます。 fire ...()呼び出しを行う前に、選択したアイテムの位置を保存します。ところで、私は呼び出しがソートや選択をリセットするとは思わない-それに問題はなかった。

列を追加する場合、キー列と新しい列の値のみを取得できます。それらを列に表示します。次に、バックグラウンドで非表示の完全な再読み込みを実行し、終了したらモデルをそのモデルに置き換えます。これは、1つのテーブルで同時に複数のResultSetから実際に機能します。

その列の値を表示しないため、削除は簡単です。

Edit3:

DefaultRowSorterはそれほど深くはありません。レコードのインデックス再作成テーブルを維持します。したがって、JTableが10行目を要求すると、rowsorterはインデックステーブルの10番目のエントリをチェックし、実際のモデルからそのindexth要素を取得します。

また、モデルに同じ文字列が多数ある場合は、データベースからデータをクエリするときに、単純な文字列から文字列へのキャッシュマップを使用します。これにより、大量の冗長なStringオブジェクトをすぐにGC-dにできます。

Edit4:

新しいフィールドをキーと値のマップに照会し、プライマリモデルにキーと値のマップのリストを含めます。次に、これらの追加マップのプライマリデータソースまたはオンデマンドのいずれかから値を返すgetValue()実装を使用します。プライマリモデルから行のキーを検索し、それを使用して追加のマップから実際の値を取得します。 (ところで、受け入れられた回答から得られる評判は、毎日の制限の対象ではありません。)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top