Наш текущий проект не использует Hibernate (по разным причинам), и мы используем поддержку Spring SimpleJdbc для выполнения всех наших операций с БД. У нас есть класс утилиты, который абстрагирует все операции CRUD, но сложные операции выполняются с использованием пользовательских SQL-запросов.
В настоящее время наши запросы хранятся как константы String внутри самих классов сервиса и передаются в утилиту, которая должна выполняться с помощью SimpleJdbcTemplate. Мы находимся в тупике, где читаемость должна быть сбалансирована с ремонтопригодностью. SQL-код внутри самого класса более удобен в обслуживании, поскольку он содержит код, который его использует. С другой стороны, если мы сохраним эти запросы во внешнем файле (плоском или XML), сам SQL будет более читабельным по сравнению с экранированным синтаксисом строки java.
Кто-нибудь сталкивался с подобной проблемой? Что такое хороший баланс? Где вы держите свой собственный SQL в своем проекте?
Пример запроса выглядит следующим образом:
private static final String FIND_ALL_BY_CHEAPEST_AND_PRODUCT_IDS =
" FROM PRODUCT_SKU T \n" +
" JOIN \n" +
" ( \n" +
" SELECT S.PRODUCT_ID, \n" +
" MIN(S.ID) as minimum_id_for_price \n" +
" FROM PRODUCT_SKU S \n" +
" WHERE S.PRODUCT_ID IN (:productIds) \n" +
" GROUP BY S.PRODUCT_ID, S.SALE_PRICE \n" +
" ) FI ON (FI.PRODUCT_ID = T.PRODUCT_ID AND FI.minimum_id_for_price = T.ID) \n" +
" JOIN \n" +
" ( \n" +
" SELECT S.PRODUCT_ID, \n" +
" MIN(S.SALE_PRICE) as minimum_price_for_product \n" +
" FROM PRODUCT_SKU S \n" +
" WHERE S.PRODUCT_ID IN (:productIds) \n" +
" GROUP BY S.PRODUCT_ID \n" +
" ) FP ON (FP.PRODUCT_ID = T.PRODUCT_ID AND FP.minimum_price_for_product = T.sale_price) \n" +
"WHERE T.PRODUCT_ID IN (:productIds)";
Вот как это выглядело бы в плоском файле SQL:
--namedQuery: FIND_ALL_BY_CHEAPEST_AND_PRODUCT_IDS
FROM PRODUCT_SKU T
JOIN
(
SELECT S.PRODUCT_ID,
MIN(S.ID) as minimum_id_for_price
FROM PRODUCT_SKU S
WHERE S.PRODUCT_ID IN (:productIds)
GROUP BY S.PRODUCT_ID, S.SALE_PRICE
) FI ON (FI.PRODUCT_ID = T.PRODUCT_ID AND FI.minimum_id_for_price = T.ID)
JOIN
(
SELECT S.PRODUCT_ID,
MIN(S.SALE_PRICE) as minimum_price_for_product
FROM PRODUCT_SKU S
WHERE S.PRODUCT_ID IN (:productIds)
GROUP BY S.PRODUCT_ID
) FP ON (FP.PRODUCT_ID = T.PRODUCT_ID AND FP.minimum_price_for_product = T.sale_price)
WHERE T.PRODUCT_ID IN (:productIds)