66 Часть I. Обзор
Считывание данных
Рассматривая проблему считывания информации из базы данных, я предпочитаю
трактовать предназначенные для этого методы в виде функций поиска (finders), скрываю-
щих посредством соответствующих входных интерфейсов SQL-выражения формата
"select". Примерами подобных методов могут служить find (id) или findForCus-
tomer (customer). Разумеется, если ваше приложение оперирует тремя десятками вы-
ражений "select" с различными критериями выбора, указанная схема становится черес-
чур громоздкой, но такие ситуации, к счастью, редки.
Принадлежность методов зависит от вида используемого интерфейсного типового
решения. Если каждый класс, обеспечивающий взаимодействие с базой данных, привя-
зан к определенной таблице, в его состав наряду с методами вставки и замены уместно
включить и методы поиска. Если же объект класса соответствует отдельной записи дан-
ных, требуется иной подход.
В этом случае можно попробовать сделать методы поиска статическими, но за это
придется заплатить некоторой долей гибкости, в частности вам более не удастся в целях
тестирования заменить базу данных фиктивной службой (Service Stub, 519). Чтобы избе-
жать подобных проблем, лучше предусмотреть специальные классы поиска, включив в
состав каждого из них методы, обеспечивающие инкапсуляцию тех или иных SQL-
запросов. В результате выполнения запроса метод возвращает коллекцию объектов, со-
ответствующих определенным записям данных.
Применяя методы поиска, следует помнить, что они выполняются в контексте со-
стояния базы данных, а не состояния объекта. Если после создания в памяти объектов-
записей данных, отвечающих некоторому критерию, вы активизируете запрос, который
предполагает поиск записей, удовлетворяющих тому же критерию, то очевидно, что объ-
екты, созданные, но не зафиксированные в базе данных, в результат обработки запроса
не попадут.
При считывании данных проблемы производительности могут приобретать первосте-
пенное значение. Необходимо помнить несколько эмпирических правил.
Старайтесь при каждом обращении к базе данных извлекать немного больше записей,
чем нужно. В частности, не выполняйте один и тот же запрос повторно для приобретения
дополнительной информации. Почти всегда предпочтительнее получить как можно
больше данных, но нужно отдавать себе отчет в том, что при использовании пессимисти-
ческой стратегии управления параллельными заданиями это может привести к ненужно-
му блокированию большого количества записей. Например, если необходимо найти
50 записей, удовлетворяющих определенному условию, лучше выполнить запрос, воз-
вращающий 200 записей, и применить для отбора искомых дополнительную логику, чем
инициировать 50 отдельных запросов.
Другой способ исключить необходимость неоднократного обращения к базе дан-
ных связан с применением операторов соединения (join), позволяющих с помощью од-
ного запроса извлечь информацию из нескольких таблиц. Итоговый набор записей
может содержать больше информации, чем требуется, но скорость его получения, ве-
роятно, выше, чем в случае выполнения нескольких запросов, возвращающих в ре-
зультате те же данные. Для этого следует воспользоваться шлюзом (Gateway, 483), охва-
тывающим информацию из нескольких таблиц, которые подлежат соединению, или