Наш текущий проект не использует Hibernate (по разным причинам), и мы используем поддержку SimpleJdbc Spring для выполнения всех наших операций с БД. У нас есть служебный класс, который абстрагирует все операции CRUD, но сложные операции выполняются с использованием пользовательских запросов SQL.
В настоящее время наши запросы хранятся в виде строковых констант внутри самих классов обслуживания и передаются в утилиту, которая будет выполняться 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)