Отображение данных значения атрибута объекта в JTable? - PullRequest
1 голос
/ 24 июня 2009

Как я могу использовать JTable для отображения и редактирования свойств атрибутов для сущностей, извлеченных из хранилища сущностей, атрибутов, значений (EAV) (реляционной СУБД)?

Я знаю, что это вопрос с множеством возможных ответов, поэтому ПОЖАЛУЙСТА, , прежде чем отвечать, ознакомьтесь с требованиями, приведенными ниже.

Я обещаю проголосовать за ответы, которые покажут, что вы все прочитали и поняли (если они не совсем глупы).


Пользователь должен иметь возможность:

  1. Фильтр / Поиск сущностей по их атрибутам

  2. Выберите, какие атрибуты показывать (в виде столбцов)

  3. Сортировка объектов по выбранным атрибутам

  4. Редактировать значения атрибута

  5. Выполнять операции на выбранных объектах

  6. (Необязательно) Возможность сохранения вида для последующего использования.


Системные требования:

  1. Количество объектов: необходимо масштабировать до 100К + уникальные объекты

  2. Атрибуты: пользователь может добавлять и определять новые атрибуты, система должна иметь возможность обрабатывать это

  3. Базовое хранилище: база данных H2 (уже спроектирована), сообщаемая JDBC

  4. Память: не все подойдет, поэтому как-то нужно тянуть из запросов к СУБД

  5. Производительность: следует минимизировать количество запросов к СУБД (один запрос на атрибут в порядке, и у меня есть форма с 1 запросом на представление таблицы, но это отстой).

  6. Запросы: ОДИН запрос должен быть необходим для генерации списка объектов, соответствующих поиску / фильтру. В противном случае массивная производительность отстой.

  7. Повторное использование данных: не нужно повторно запрашивать или повторно сортировать весь список при добавлении столбца.


Вещи, на которые я смотрел:

  1. Библиотека Glazed Lists

    • Плюсы:

      • Гибкость в обработке столбцов
      • Простая реализация сортировки / фильтрации объектов
      • Гибкий формат отображения и редактирования столбцов
    • Минусы:

      • Один объект на объект (если объекты сложны, накладные расходы памяти становятся серьезной проблемой памяти!)
      • Объект отвечает за все функции ... но объекты должны быть простыми по соображениям памяти
      • Как мне поддерживать выбираемые пользователем столбцы без HashMap для КАЖДОГО объекта сущности?
  2. Расширение AbstractTableModel для сопоставления данных из ResultSet JDBC со строками, столбцами

    • Плюсы:
      • Пейджинг результатов позволяет избежать проблем с памятью
      • Поиск / фильтрация напрямую в SQL
      • Удобен для памяти, не нужно создавать объект для каждой строки
    • Минусы:
      • Реализация пользовательских столбцов и сортировка - это трудная задача (средство визуализации заголовка таблицы, управление столбцами сортировки и порядком и т. Д.)!
      • Вероятно, придется написать собственный JTableColumnModel, и это будет грязно!
      • Нужно много манипулировать SQL, поэтому, если схема БД меняется, нужно переписать несколько кусков кода!
      • Трудно поддерживать информацию об идентификаторе сущности
  3. ORM

    • Плюсы:
      • Предназначен для сопоставления строк БД с объектами
      • Обеспечивает управление объектами
    • Минусы:
      • НАИБОЛЕЕ ВОЗМОЖНОЕ решение для модели атрибут-значение-сущность
      • Необходимо выучить и написать код ORM в дополнение к СУБД и коду Java!
      • Сущности могут иметь любое количество атрибутов, ORM подходит только для статических, ограниченных атрибутов объекта
      • Потеря гибкости / скорости пользовательского SQL

Есть ли лучший вариант, который я пропустил, или какой-нибудь более умный способ сделать Glazed Lists или пользовательскую модель таблицы проще? Я уже полностью отказался от ORM в качестве опции из-за того, насколько плохо он соответствует хранилищу EAV.

1 Ответ

1 голос
/ 24 июня 2009

Я думаю, что ваш лучший вариант - использовать 'Расширение AbstractTableModel с данными карты формы из JDBC ResultSet', потому что

  • Java 6 JTable имеет встроенную поддержку сортировки, поэтому вам не нужно реализовывать это.
  • Если вы тщательно спроектируете свою модель, вы сможете пережить некоторые изменения схемы. Четко кодируйте, чтобы вам было легче вносить изменения, если вам нужно.
  • Вам все равно придется записывать изменения. Используйте кнопку «Сохранить», и пакетное обновление может даже улучшить вашу производительность.
  • Вы можете переопределить TableCellEditor для предоставления комбинированного списка вместо текстового редактора по умолчанию.
  • Не пытайтесь делать все изменения в одной таблице. Отделили средства для создания записи и т. Д.
  • Вы можете добавлять / удалять столбцы в JTable во время выполнения. Просто fireTableModelChanged () и новый столбец становится видимым

Редактировать: Одна сумасшедшая вещь, которую я хотел бы сделать, чтобы создать собственный компонент и сделать все отрисовки самостоятельно и выполнять операции редактирования с хорошо расположенными JTextField и JComboBox.

Edit2: На основании вашего комментария. Сохраните позицию выбранного элемента, прежде чем выполнить вызов fire ... (). Кстати, я не думаю, что вызов сбрасывает сортировку или выбор - не было никаких проблем с этим.

Если вы добавите столбец, вы можете просто получить ключевое поле и значения только для нового столбца. Отобразите их в столбце. Затем выполните скрытую полную перезагрузку в фоновом режиме и поменяйте модель на нее, когда она будет завершена. Это практически работает из нескольких ResultSets одновременно в одной таблице.

Удаление легко, так как вы не показываете значения для этого столбца.

Edit3:

DefaultRowSorter не такой глубокий. Он поддерживает таблицу переиндексации для ваших записей. Поэтому, когда JTable запрашивает 10-ую строку, сортировщик строк проверяет свою 10-ую запись индексной таблицы и извлекает этот элемент индекса из вашей фактической модели.

Также, если в вашей модели много одинаковых строк, используйте простой кэш Map of String to String при запросе данных из базы данных. Таким образом, тонны избыточных объектов String могут быть сразу получены GC-d.

Edit4:

Я бы запросил новое поле в Map of key to value, и моя основная модель содержала бы список map of value. Затем я бы использовал реализацию getValue (), которая возвращает значение из первичного источника данных из этих дополнительных карт по запросу. Я хотел бы найти ключ строки в основной модели и использовать его для получения фактического значения из дополнительных карт. (Кстати. Репутация, полученная из принятых ответов, не зависит от дневного лимита.)

...