現在のプロジェクトは (さまざまな理由で) Hibernate を使用しておらず、Spring の SimpleJdbc サポートを使用してすべての DB 操作を実行しています。すべての CRUD 操作を抽象化するユーティリティ クラスがありますが、複雑な操作はカスタム SQL クエリを使用して実行されます。
現在、クエリはサービス クラス自体の内部に文字列定数として格納され、SimpleJdbcTemplate によって実行されるユーティリティに供給されます。私たちは、可読性と保守性のバランスを取らなければならない行き詰まりに陥っています。クラス自体の内部の SQL コードは、それを使用するコードと共に常駐するため、より保守しやすくなります。一方、これらのクエリを外部ファイル (フラットまたは XML) に格納すると、エスケープされた Java 文字列構文と比較して、SQL 自体が読みやすくなります。
誰かが同様の問題に遭遇しましたか? 良いバランスとは?カスタム 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)