Каков правильный шаблон кода для выборки записей базы данных? - PullRequest
1 голос
/ 18 октября 2011

В двух других вопросах ( здесь и здесь ) BalusC делает прямое заявление:

Геттеры находятся исключительно там, чтобы получить доступ свойств бина, чтобы не заниматься бизнес-логикой.Там у вас есть конструктор компонента, блоки инициализации или методы события.Все выполняются только один раз за время жизни бина, и это именно то, что вы хотите.

Ну и дела - это просто лишило законной силы миллионный ряд кода, который я уже написал.Хорошо, тогда каков правильный способ реализации бина, который заполняет таблицу данных?Я понимаю его точку зрения и концепцию, но не практику.У меня двоякий вопрос:

  1. Почему я делаю это неправильно?
  2. Как мне это исправить?

Я использую PrimeFaces p: dataTable много, а его атрибут value разрешается в коллекцию.По причинам, которые я здесь не обсуждаю, я , а не использую функцию отложенной загрузки таблиц PrimeFaces.Вместо этого я реализую свои собственные элементы управления фильтром / сортировкой, но они запускают события AJAX, в результате чего таблица заполняется записями, извлеченными из базы данных.

Таблица размечена так:

 <p:panel id="mqTable">

   <h:outputText value="Sort/Filter: #{maintCategory.tableQueryParameters}" />

   <p:dataTable
      id="mqDataTable"
      rows="#{maintCategory.pageSize}"
      value="#{maintCategory.dataModel}"
      selection="#{maintCategory.selected}"
      var="cat"
      selectionMode="single"
      emptyMessage="No Categories Found">

Теперь НЕВЕРОЯТНО ПЛОХОЙ UN-JSFish (или так я только что узнал) геттер для dataModel выглядит так:

public ATMDataModel getDataModel() {
    TableQueryParameters p = getTableQueryParameters();
    if (p.isChangePending()) clearDataModel();
    p.setChangePending(false);
    if (dataModel != null) return dataModel;
    List<ET> list = getDAO().runQuery(p);
    if (p.isNeedResultSize()) p.setResultSize(getDAO().runQueryCount(p));
    dataModel = new ATMDataModel(list);
    return dataModel;
}

Несколько объяснений.

  1. Это из абстрактного суперкласса, где ET - это «Тип сущности».Все мои CRUDы используют эту же процедуру.
  2. Класс ATMDataModel - это оболочка для списка, которая реализует SelectableListModel .Логика выбора строк в PrimeFaces требует этого.(Это боль, которая появилась в PF 3, но она делает выбор строк более надежным.)
  3. Класс TableQueryParameters - это то, что я написал, чтобы инкапсулировать текущее состояние таблицы пользователяэкран.Он включает параметры сортировки, параметры фильтра, страницу, на которой мы находимся и т. Д. Поскольку это необходимо сохранить, базовый компонент имеет вид ViewAccesScoped (через MyFaces CODI) и TableQueryParameters это свойство внутри него.
  4. TableQueryParameters обновляются в ответ через события AJAX, которые также обновляют форму, вызывая getDataModel .Метод isChangePending переходит true , когда что-то меняется.Таким образом, метод getDataModel использует его для генерации только одной выборки из DAO между изменениями, независимо от того, сколько раз он вызывается.

НО , если TableQueryParameters do изменить, мне нужно вызвать runQuery с этими параметрами, чтобы получить новый набор записей, которые пользователь хочет видеть.Если я не позвоню в getDataModel , где мне это назвать?

Пожалуйста, сообщите.

1 Ответ

1 голос
/ 18 октября 2011

Вы в основном лениво загружаете данные в геттер. Вы не обращаетесь к БД при каждом вызове геттера в пределах одной и той же области запроса (или просмотра). Это доступно. Я не использую CODI, но я думаю, что вызов getTableQueryParameters() также особенно дешев и не о чем беспокоиться.

Что касается конкретного вопроса, вы обычно выполняете работу с БД / бизнесом в методе действия (слушателя), который присоединен к компоненту UICommand и / или тегу события ajax.

Например (работает также как <p:commandButton action> хотя)

<p:ajax listener="#{bean.deleteSelectedRow}" />
...
<p:ajax listener="#{bean.saveRowDetail}" />

с

public void deleteSelectedRow() {
    someService.delete(selectedRow);
    dataModel = loadDataModel();
}

public void saveRowDetail() {
    someService.save(selectedRow);
    dataModel = loadDataModel();
}

В зависимости от значения p.isChangePending(), я думаю, вы могли бы также избавиться от него таким образом, похоже, что вы устанавливали его в методах действия (слушателя).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...