Слой взаимодействия с БД

Lightning

Трудоголик
Слой взаимодействия с БД

Знаю, что тема неоднократно обсуждалась, но это обычно было в форме холиваров. Хотелось бы обсудить эти вопросы более развернуто и спокойно, изложить свои мысли и послушать умных людей, собрать все аргументы в этот топик.
Моя попытка проанализировать типичные решения, используемые для организации слоя взаимодействия с БД:

1. Использование шаблонов SQL-запросов.
Плюсы:
- "Прозрачность".
Минусы:
- Слабая гибкость (Одно изменение в проекте может потребовать затронуть множество шаблонов запросов)
- Слабая портируемость (При переходе на другую СУБД необходимо переписывать весь слой взаимодействия с БД).
2. Конструкторы SQL-запросов.
Плюсы:
- Гибкость.
- Портируемость.
Минусы:
- "Непрозрачность" (Возможны трудности с поиском мест, где какой-либо запрос собирается).
3. ОРМ.
Плюсы:
- Снижение сложности (Т.к. ОРМ предоставляет более высокий уровень абстракции).
- Увелечение скорости разработки.
- Гибкость.
- Портируемость.
Минусы:
- Полнейшая "непрозрачность" и, как следствие, сложности с отладкой и оптимизацией запросов.
4. Хранимые процедуры БД.
Плюсы:
- "Прозрачность".
- Гибкость.
- Полное отделение логики работы с БД.
Минусы:
- Сложности рефакторинга, тестирования и контроля версий.
- Слабая портируемость.

Вопросы:
1. Какие из перечисленных решений Вы используете и почему?
2. Какие еще плюсы или минусы существуют у перечисленных в посте решений?
3. Существуют ли еще какие-либо решения организации слоя взаимодействия с БД?

P.S. Я обычно использую нечто похожее на самописный конструктор SQL запросов.
 

dimagolov

Новичок
4. Хранимые процедуры БД.
а выборки как делать при этом?
ИМХО хранимые процедуры хороши тогда, когда надо при изменении БД необходимо гарантировать корректность представления модели в БД. В них отлично упаковываются транзакции, но далеко не всегда, так как передать массивы в них по меньшей мере затруднительно. То есть это один из приемов, который может использоваться с каким-то иным методом взаимодействия с БД.
 

Духовность™

Продвинутый новичок
приведи примеры того, что ты называешь.. а то так как-то сложно ориентироваться. Что такое шаблоны?
 

Lightning

Трудоголик
Что такое шаблоны?
Просто шаблоны прямых запросов к базе.
Например:
PHP:
$sql = 'SELET * FROM sometable WHERE filed1=%s and field2=%d';
Или еще круче
PHP:
$sql = 'SELECT {IF count} count(*) {ELSE} * {ENDIF} FROM sometable ...';
dimagolov
а выборки как делать при этом?
Выборки можно полностью "упаковать" в хранимые процедуры. Некоторые так делают.
 

dimagolov

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

Lightning

Трудоголик
dimagolov
Пример. Процедура выбирающая несколько произвольных записей из таблицы:
Код:
CREATE PROCEDURE `RandomSelect`(IN aSchema VARCHAR(50), IN aTable VARCHAR(50), IN aNumRows INTEGER(11))
    NOT DETERMINISTIC
    READS SQL DАТА
BEGIN
  DECLARE iQuery VARCHAR(10000);
  DECLARE iNumRows INTEGER(11);

  SET iNumRows = (SELECT `TABLE_ROWS` FROM `information_schema`.`TABLES` t
    WHERE t.`TABLE_SCHEMA` = aSchema AND t.`TABLE_NAME` = aTable);
  SET iQuery = '';
  loop1: LOOP
    SET iQuery = CONCAT(iQuery, '(SELECT * FROM `', aSchema, '`.`', aTable,
      '` LIMIT ', ROUND(RAND(UNIX_TIMESTAMP() + aNumRows) * iNumRows), ', 1)');
    IF aNumRows > 1 THEN
      SET iQuery = CONCAT(iQuery, ' UNION ');
    END IF;
    SET aNumRows = aNumRows - 1;
    IF aNumRows > 0 THEN
      ITERATE loop1;
    END IF;
    LEAVE loop1;
  END LOOP loop1;
  SET @iQuery = iQuery;
  PREPARE iExecStmt FROM @iQuery;
  EXECUTE iExecStmt;
  DRОP PREPARE iExecStmt;
END;
 

zerkms

TDD infected
Команда форума
используем 2 + 3. связка как таковая очень-очень-очень удобна.
 

atv

Новичок
2 + 3, при хорошем оформлении кода никакой непрозрачности не возникает, благо, средства языка позволяют.

В своё время для одного из экономических порталов писал вывод финансовой отчётности компаний, причём в разных форматах, в зависимости от отчёта, страны, разреза данных и многих других условий.

Вся логика построения запроса была помещена в один высокоуровневый класс, которому передавались необходимые параметры, а уже сам класс использовал SQL конструктор. Получилось всё в одном месте и достаточно прозрачно.

На SQL шаблонах с такими запросами пришлось бы хорошенько повозиться.
 

Lightning

Трудоголик
используем 2 + 3.
Можно подробнее, для каких запросов ОРМ, а для каких конструктор? Я, если честно, не представляю, как можно мешать два этих подхода и не запутаться.
 

zerkms

TDD infected
Команда форума
Lightning
конструктор пользуется внутри орм для генерации своих запросов:

PHP:
        foreach ($this->getSelectFields($mapper) as $field) {
            $criteria->addSelectField($alias . '.' . $field, $alias . self::TABLE_KEY_DELIMITER . $field);
        }
PHP:
        foreach ($orderBy as $val) {
            $val['direction'] == 'asc' ? $criteria->setOrderByFieldAsc($val['key']) : $criteria->setOrderByFieldDesc($val['key']);;
        }
(c) class mapper

и снаружи - для передачи критериев мапперу:

PHP:
$criteria = new criteria();
$criteria->setLimit(10)->setOrderByDesc('id');
$collection = $mapper->searchAllByCriteria($criteria);
 

Lightning

Трудоголик
Cпасибо zerkms, x-yuri и atv.
У остальных, наверное, работа с БД - коммерческая тайна? :)
 

Духовность™

Продвинутый новичок
у меня говнокод, по внешним параметрам извлекает из БД

PHP:
$this->group_mapper = new Group_Mapper();
$params = array
(
    'limit' => array('start' => $navigation->getStartLimit(), 
                     'stop' => $navigation->getStopLimit()),
    'order' => array($this->request->sort => 'ASC'),
);

$this->view->groups = $this->group_mapper->getObjectList($params)->getData();
 

Духовность™

Продвинутый новичок
Lightning
Да, одиночные объекты эта хрень нормально получает. Но когда нужно объединять таблицы... ИМХО ORM это самое трудное в разработке под веб. А написать что-то качественное - не хватает рабочего времени. А личное время тратить лень )

У zerkms-а прикольные рюшечки хихи
 

Lightning

Трудоголик
Да, одиночные объекты эта хрень нормально получает. Но когда нужно объединять таблицы...
Если нужно объединить таблицы, это еще не значит, что нужно делать вложенные объекты.
Я, если честно, не считаю, что ОРМ - это лучший вариант для Web-а. Я работал с ОРМ, но не в PHP и не для Web-а и бизнес логика там была навороченная. А в большинстве Web-приложений, где вся бизнес логика сводится к манипулированию контентом, ОРМ не нужен, ИМХО конечно.
Но и если писать просто SQL-шаблоны, то получается уж слишком много одинакового кода со всеми вытекающими последствиями. Собственно поэтому и использую нечто похожее на конструктор. Но с ним тоже свои нюансы.
У zerkms-а прикольные рюшечки хихи
Да, mzz я смотрел, прикольная штука.
 

atv

Новичок
Можно подробнее, для каких запросов ОРМ, а для каких конструктор?
Я для себя сделал следующее организационное разделение (и другим рекомендую).

Для запросов, которые выбирают сводные данные для отчётов я ОРМ не использую, так как такие запросы не входят в область применения ОРМ.

Бизнес логика для таких запросов, в основном, заключается в представлении данных (форматирование, раскраска и т.д.), причём представление, как правило, зависит от конкретного отчёта, т.е. не реюзабельно. Поместить эту бизнес логику в объект не получиться.

В таких запросах используются данные из множества таблиц, зачастую с такими связями, которые для ОРМ не используются, и тоже, в зависимости от отчёта. Часто используются вычисления, которые, по сути, не имеют отношения к Объектно-Реляционному Отображению.

Использование ОРМ, при котором создаётся множество объектов, чтобы потом повыдёргивать некоторые данные из них с единственной целью, отобразить их, я считаю нерациональным.

В остальных случаях я использую ОРМ, т.е. для сохранения, удаления, изменения данных, для получения данных необходимых при выполнении бизнес логики.

А в большинстве Web-приложений, где вся бизнес логика сводится к манипулированию контентом, ОРМ не нужен, ИМХО конечно.
Банальный интернет магазин уже обилует таким количеством бизнес логики, что ОРМ оправдывает себя на 100 процентов. А интернет магазин это уже не самый сложный проект на сегодняшний день.
 

Lightning

Трудоголик
Использование ОРМ, при котором создаётся множество объектов, чтобы потом повыдёргивать некоторые данные из них с единственной целью, отобразить их, я считаю нерациональным
+1000
Банальный интернет магазин уже обилует таким количеством бизнес логики, что ОРМ оправдывает себя на 100 процентов. А интернет магазин это уже не самый сложный проект на сегодняшний день.
Смотря какой магазин. Если действительно банальный, то там не такая уж и сложная бизнес-логика: в основном расчеты суммы заказов, учитывая доставку, скидки, курсы валют и т.д., расчеты скидок (если они есть), работа с системами оплаты, ну а все остальное - банальные операции с контентом.

-~{}~ 14.06.09 23:40:

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